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

oscerd 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 e37450999b02 CAMEL-23456: camel-docling - extract document title and 
type metadata in EXTRACT_METADATA (#24245)
e37450999b02 is described below

commit e37450999b02c897ab7f32c8076e050d34c51926
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Jun 25 14:09:33 2026 +0200

    CAMEL-23456: camel-docling - extract document title and type metadata in 
EXTRACT_METADATA (#24245)
    
    The EXTRACT_METADATA operation now populates the title and documentType
    fields on DocumentMetadata (and the CamelDoclingMetadataTitle /
    CamelDoclingMetadataDocumentType headers) when the information can be
    determined from the document. The title is taken from the first text item
    that Docling labels as a document title; the documentType is derived from
    the source file extension, falling back to the MIME subtype.
    
    Previously both fields did not exist on DocumentMetadata and the related
    assertions in MetadataExtractionIT were disabled with TODO comments. The
    title/documentType assertions are now enabled.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
---
 .../apache/camel/catalog/components/docling.json   | 19 +++----
 .../apache/camel/component/docling/docling.json    | 19 +++----
 .../src/main/docs/docling-component.adoc           | 10 ++--
 .../camel/component/docling/DoclingHeaders.java    |  3 ++
 .../camel/component/docling/DoclingProducer.java   | 61 ++++++++++++++++++++++
 .../camel/component/docling/DocumentMetadata.java  | 30 +++++++++++
 .../docling/integration/MetadataExtractionIT.java  |  4 +-
 .../ROOT/pages/camel-4x-upgrade-guide-4_21.adoc    |  8 +++
 .../dsl/DoclingEndpointBuilderFactory.java         | 12 +++++
 9 files changed, 141 insertions(+), 25 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json
index 7d7c78c7d667..46afe44b8955 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json
@@ -101,15 +101,16 @@
     "CamelDoclingBatchProcessingTime": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Total processing time for the batch in 
milliseconds", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#BATCH_PROCESSING_TIME" },
     "CamelDoclingBatchSplitResults": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Split batch results into individual 
exchanges instead of single BatchProcessingResults", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#BATCH_SPLIT_RESULTS" },
     "CamelDoclingMetadataPageCount": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Number of pages in the document", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_PAGE_COUNT" },
-    "CamelDoclingMetadataLanguage": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document language code", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_LANGUAGE" },
-    "CamelDoclingMetadataDocumentType": { "index": 23, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document type\/format", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_DOCUMENT_TYPE" },
-    "CamelDoclingMetadataFormat": { "index": 24, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document format (MIME type)", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FORMAT" },
-    "CamelDoclingMetadataFileSize": { "index": 25, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File size in bytes", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_SIZE" },
-    "CamelDoclingMetadataFileName": { "index": 26, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File name", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_NAME" },
-    "CamelDoclingMetadataRaw": { "index": 27, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Raw metadata fields as a Map", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_RAW" },
-    "CamelDoclingChunkingTokenizer": { "index": 28, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Tokenizer for hybrid chunking (e.g. 
sentence-transformers\/all-MiniLM-L6-v2)", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_TOKENIZER" },
-    "CamelDoclingChunkingMaxTokens": { "index": 29, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Maximum tokens per chunk for hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" },
-    "CamelDoclingChunkingMergePeers": { "index": 30, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Whether to merge peer chunks in hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" }
+    "CamelDoclingMetadataTitle": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document title", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_TITLE" },
+    "CamelDoclingMetadataLanguage": { "index": 23, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document language code", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_LANGUAGE" },
+    "CamelDoclingMetadataDocumentType": { "index": 24, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document type\/format", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_DOCUMENT_TYPE" },
+    "CamelDoclingMetadataFormat": { "index": 25, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document format (MIME type)", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FORMAT" },
+    "CamelDoclingMetadataFileSize": { "index": 26, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File size in bytes", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_SIZE" },
+    "CamelDoclingMetadataFileName": { "index": 27, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File name", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_NAME" },
+    "CamelDoclingMetadataRaw": { "index": 28, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Raw metadata fields as a Map", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_RAW" },
+    "CamelDoclingChunkingTokenizer": { "index": 29, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Tokenizer for hybrid chunking (e.g. 
sentence-transformers\/all-MiniLM-L6-v2)", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_TOKENIZER" },
+    "CamelDoclingChunkingMaxTokens": { "index": 30, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Maximum tokens per chunk for hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" },
+    "CamelDoclingChunkingMergePeers": { "index": 31, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Whether to merge peer chunks in hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" }
   },
   "properties": {
     "operationId": { "index": 0, "kind": "path", "displayName": "Operation 
Id", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The operation identifier" 
},
diff --git 
a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json
 
b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json
index 7d7c78c7d667..46afe44b8955 100644
--- 
a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json
+++ 
b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json
@@ -101,15 +101,16 @@
     "CamelDoclingBatchProcessingTime": { "index": 19, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Total processing time for the batch in 
milliseconds", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#BATCH_PROCESSING_TIME" },
     "CamelDoclingBatchSplitResults": { "index": 20, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Split batch results into individual 
exchanges instead of single BatchProcessingResults", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#BATCH_SPLIT_RESULTS" },
     "CamelDoclingMetadataPageCount": { "index": 21, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Number of pages in the document", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_PAGE_COUNT" },
-    "CamelDoclingMetadataLanguage": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document language code", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_LANGUAGE" },
-    "CamelDoclingMetadataDocumentType": { "index": 23, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document type\/format", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_DOCUMENT_TYPE" },
-    "CamelDoclingMetadataFormat": { "index": 24, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document format (MIME type)", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FORMAT" },
-    "CamelDoclingMetadataFileSize": { "index": 25, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File size in bytes", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_SIZE" },
-    "CamelDoclingMetadataFileName": { "index": 26, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File name", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_NAME" },
-    "CamelDoclingMetadataRaw": { "index": 27, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Raw metadata fields as a Map", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_RAW" },
-    "CamelDoclingChunkingTokenizer": { "index": 28, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Tokenizer for hybrid chunking (e.g. 
sentence-transformers\/all-MiniLM-L6-v2)", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_TOKENIZER" },
-    "CamelDoclingChunkingMaxTokens": { "index": 29, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Maximum tokens per chunk for hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" },
-    "CamelDoclingChunkingMergePeers": { "index": 30, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Whether to merge peer chunks in hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" }
+    "CamelDoclingMetadataTitle": { "index": 22, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document title", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_TITLE" },
+    "CamelDoclingMetadataLanguage": { "index": 23, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document language code", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_LANGUAGE" },
+    "CamelDoclingMetadataDocumentType": { "index": 24, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document type\/format", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_DOCUMENT_TYPE" },
+    "CamelDoclingMetadataFormat": { "index": 25, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Document format (MIME type)", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FORMAT" },
+    "CamelDoclingMetadataFileSize": { "index": 26, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File size in bytes", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_SIZE" },
+    "CamelDoclingMetadataFileName": { "index": 27, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "File name", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_FILE_NAME" },
+    "CamelDoclingMetadataRaw": { "index": 28, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"Map<String, Object>", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Raw metadata fields as a Map", 
"constantName": 
"org.apache.camel.component.docling.DoclingHeaders#METADATA_RAW" },
+    "CamelDoclingChunkingTokenizer": { "index": 29, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Tokenizer for hybrid chunking (e.g. 
sentence-transformers\/all-MiniLM-L6-v2)", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_TOKENIZER" },
+    "CamelDoclingChunkingMaxTokens": { "index": 30, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Maximum tokens per chunk for hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" },
+    "CamelDoclingChunkingMergePeers": { "index": 31, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Whether to merge peer chunks in hybrid 
chunking", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" }
   },
   "properties": {
     "operationId": { "index": 0, "kind": "path", "displayName": "Operation 
Id", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The operation identifier" 
},
diff --git 
a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc 
b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc
index 57f77bddea62..ccdf462717a1 100644
--- a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc
+++ b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc
@@ -448,12 +448,12 @@ from("file:///data/documents?include=.*\\.pdf")
 
         // Access metadata fields
         String title = metadata.getTitle();
-        String author = metadata.getAuthor();
+        String documentType = metadata.getDocumentType();
         Integer pageCount = metadata.getPageCount();
-        Instant creationDate = metadata.getCreationDate();
+        String format = metadata.getFormat();
 
-        log.info("Document: {} by {}, Pages: {}, Created: {}",
-            title, author, pageCount, creationDate);
+        log.info("Document: {} ({}), Pages: {}, Format: {}",
+            title, documentType, pageCount, format);
 
         // Metadata is also available in headers
         String titleFromHeader = 
exchange.getIn().getHeader("CamelDoclingMetadataTitle", String.class);
@@ -473,7 +473,7 @@ YAML::
       - to:
           uri: docling:EXTRACT_METADATA
       - log:
-          message: "Document: ${header.CamelDoclingMetadataTitle} by 
${header.CamelDoclingMetadataAuthor}"
+          message: "Document: ${header.CamelDoclingMetadataTitle} 
(${header.CamelDoclingMetadataDocumentType})"
       - log:
           message: "Pages: ${header.CamelDoclingMetadataPageCount}"
       - process:
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingHeaders.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingHeaders.java
index 5f19834daa06..8c4aac66e4cd 100644
--- 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingHeaders.java
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingHeaders.java
@@ -87,6 +87,9 @@ public final class DoclingHeaders {
     @Metadata(description = "Number of pages in the document", javaType = 
"Integer")
     public static final String METADATA_PAGE_COUNT = 
"CamelDoclingMetadataPageCount";
 
+    @Metadata(description = "Document title", javaType = "String")
+    public static final String METADATA_TITLE = "CamelDoclingMetadataTitle";
+
     @Metadata(description = "Document language code", javaType = "String")
     public static final String METADATA_LANGUAGE = 
"CamelDoclingMetadataLanguage";
 
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java
index 4129db3858a0..cd970853e290 100644
--- 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java
@@ -34,6 +34,7 @@ import java.util.Base64;
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -50,6 +51,8 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import ai.docling.core.DoclingDocument;
+import ai.docling.core.DoclingDocument.BaseTextItem;
+import ai.docling.core.DoclingDocument.DocItemLabel;
 import ai.docling.core.DoclingDocument.DocumentOrigin;
 import ai.docling.serve.api.DoclingServeApi;
 import ai.docling.serve.api.chunk.request.ChunkDocumentRequest;
@@ -681,6 +684,9 @@ public class DoclingProducer extends DefaultProducer {
                 metadata.setFormat(origin.getMimetype());
             }
 
+            metadata.setDocumentType(deriveDocumentType(origin));
+            metadata.setTitle(extractTitle(doclingDocument));
+
             // Store raw metadata if requested
             if (configuration.isIncludeRawMetadata()) {
                 @SuppressWarnings("unchecked")
@@ -729,6 +735,9 @@ public class DoclingProducer extends DefaultProducer {
                 metadata.setFormat(origin.getMimetype());
             }
 
+            metadata.setDocumentType(deriveDocumentType(origin));
+            metadata.setTitle(extractTitle(doclingDocument));
+
             // Store raw metadata if configured
             if (configuration.isIncludeRawMetadata()) {
                 JsonNode rootNode = objectMapper.readTree(jsonOutput);
@@ -745,6 +754,12 @@ public class DoclingProducer extends DefaultProducer {
     }
 
     private void setMetadataHeaders(Exchange exchange, DocumentMetadata 
metadata) {
+        if (metadata.getTitle() != null) {
+            exchange.getIn().setHeader(DoclingHeaders.METADATA_TITLE, 
metadata.getTitle());
+        }
+        if (metadata.getDocumentType() != null) {
+            exchange.getIn().setHeader(DoclingHeaders.METADATA_DOCUMENT_TYPE, 
metadata.getDocumentType());
+        }
         if (metadata.getPageCount() != null) {
             exchange.getIn().setHeader(DoclingHeaders.METADATA_PAGE_COUNT, 
metadata.getPageCount());
         }
@@ -763,6 +778,52 @@ public class DoclingProducer extends DefaultProducer {
         }
     }
 
+    /**
+     * Extracts the document title from the Docling document, defined as the 
first text item labelled as
+     * {@link DocItemLabel#TITLE}. Returns {@code null} when the document does 
not expose a title.
+     */
+    private String extractTitle(DoclingDocument doclingDocument) {
+        List<BaseTextItem> texts = doclingDocument.getTexts();
+        if (texts == null) {
+            return null;
+        }
+        for (BaseTextItem item : texts) {
+            if (item != null && item.getLabel() == DocItemLabel.TITLE) {
+                String text = item.getText();
+                if (text != null && !text.isBlank()) {
+                    return text.trim();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Derives a short, human-readable document type (e.g., {@code PDF}, 
{@code DOCX}) from the document origin,
+     * preferring the source file extension and falling back to the MIME 
subtype. Returns {@code null} when the type
+     * cannot be determined.
+     */
+    private String deriveDocumentType(DocumentOrigin origin) {
+        if (origin == null) {
+            return null;
+        }
+        String filename = origin.getFilename();
+        if (filename != null) {
+            int dot = filename.lastIndexOf('.');
+            if (dot > 0 && dot < filename.length() - 1) {
+                return filename.substring(dot + 1).toUpperCase(Locale.ROOT);
+            }
+        }
+        String mimetype = origin.getMimetype();
+        if (mimetype != null && !mimetype.isBlank()) {
+            int slash = mimetype.lastIndexOf('/');
+            String subtype = slash >= 0 && slash < mimetype.length() - 1
+                    ? mimetype.substring(slash + 1) : mimetype;
+            return subtype.toUpperCase(Locale.ROOT);
+        }
+        return null;
+    }
+
     private void processBatchConversion(Exchange exchange, String 
outputFormat) throws Exception {
         LOG.debug("DoclingProducer processing batch conversion with format: 
{}", outputFormat);
 
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DocumentMetadata.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DocumentMetadata.java
index 240a3cb24f1f..b903b4cd82d4 100644
--- 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DocumentMetadata.java
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DocumentMetadata.java
@@ -24,6 +24,8 @@ import java.util.Map;
  */
 public class DocumentMetadata {
 
+    private String title;
+    private String documentType;
     private Integer pageCount;
     private String format;
     private Long fileSizeBytes;
@@ -35,6 +37,32 @@ public class DocumentMetadata {
         this.rawMetadata = new HashMap<>();
     }
 
+    /**
+     * Gets the document title as detected by Docling (the text labelled as 
the document title), when present.
+     *
+     * @return the document title, or {@code null} if the source document does 
not expose one
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    /**
+     * Gets the document type derived from the source (e.g., "PDF", "DOCX"), 
when it can be determined.
+     *
+     * @return the document type, or {@code null} if it cannot be determined
+     */
+    public String getDocumentType() {
+        return documentType;
+    }
+
+    public void setDocumentType(String documentType) {
+        this.documentType = documentType;
+    }
+
     /**
      * Gets the number of pages in the document.
      *
@@ -138,6 +166,8 @@ public class DocumentMetadata {
     @Override
     public String toString() {
         return "DocumentMetadata{"
+               + "title='" + title + '\''
+               + ", documentType='" + documentType + '\''
                + ", pageCount=" + pageCount
                + ", format='" + format + '\''
                + ", fileSizeBytes=" + fileSizeBytes + ", fileName='" + 
fileName + '\'' + ", filePath='" + filePath + '\''
diff --git 
a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/integration/MetadataExtractionIT.java
 
b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/integration/MetadataExtractionIT.java
index 9886e2e63a81..45303a0368c7 100644
--- 
a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/integration/MetadataExtractionIT.java
+++ 
b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/integration/MetadataExtractionIT.java
@@ -71,8 +71,8 @@ class MetadataExtractionIT extends DoclingITestSupport {
         assertNotNull(metadata.getFilePath(), "File path should be set");
         assertThat(metadata.getPageCount()).isEqualTo(5);
         assertThat(metadata.getFormat()).isEqualTo("application/pdf");
-        // TODO: assertThat(metadata.getTitle()).isEqualTo("The Evolution of 
the Word Processor");
-        // TODO: assertThat(metadata.getDocumentType()).isEqualTo("PDF");
+        assertThat(metadata.getTitle()).isEqualTo("The Evolution of the Word 
Processor");
+        assertThat(metadata.getDocumentType()).isEqualTo("PDF");
 
         LOG.info("Successfully extracted metadata: {}", metadata);
         LOG.info("File name: {}", metadata.getFileName());
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 5dec2e266e8b..4e8e7d3121d3 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
@@ -13,6 +13,14 @@ See the xref:camel-upgrade-recipes-tool.adoc[documentation] 
page for details.
 
 == Upgrading Camel 4.20 to 4.21
 
+=== camel-docling
+
+The `EXTRACT_METADATA` operation now populates the `title` and `documentType` 
fields on the returned
+`DocumentMetadata` (and the corresponding `CamelDoclingMetadataTitle` and 
`CamelDoclingMetadataDocumentType`
+headers) when the information can be determined from the document. The title 
is taken from the document title
+detected by Docling, and the document type is derived from the source file 
extension or MIME type. Previously
+these two fields were always empty.
+
 === camel-grok - potential breaking change
 
 The library used for Camel Grok component has been migrated from no more 
maintained `io.krakens:java-grok` to its fork `io.github.whatap:java-grok`.
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DoclingEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DoclingEndpointBuilderFactory.java
index 22e2b26bb47b..dcb0f400e56f 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DoclingEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DoclingEndpointBuilderFactory.java
@@ -1741,6 +1741,18 @@ public interface DoclingEndpointBuilderFactory {
         public String doclingMetadataPageCount() {
             return "CamelDoclingMetadataPageCount";
         }
+        /**
+         * Document title.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code DoclingMetadataTitle}.
+         */
+        public String doclingMetadataTitle() {
+            return "CamelDoclingMetadataTitle";
+        }
         /**
          * Document language code.
          * 

Reply via email to