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

acosentino pushed a commit to branch CAMEL-22547
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1b6130bfcdb1e7b1dcaa7eaf4363bcaf33e51fa3
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Oct 15 09:21:03 2025 +0200

    CAMEL-22547 - Camel-Docling: Support Async operation in docling-server
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../docling/DoclingComponentConfigurer.java        |  24 ++
 .../docling/DoclingConfigurationConfigurer.java    |  24 ++
 .../docling/DoclingEndpointConfigurer.java         |  24 ++
 .../docling/DoclingEndpointUriFactory.java         |   6 +-
 .../apache/camel/component/docling/docling.json    |  48 ++--
 .../src/main/docs/docling-component.adoc           | 139 ++++++++++
 .../camel/component/docling/ConversionStatus.java  |  91 +++++++
 .../component/docling/DoclingConfiguration.java    |  48 ++++
 .../camel/component/docling/DoclingHeaders.java    |  12 +
 .../camel/component/docling/DoclingProducer.java   |  42 ++-
 .../component/docling/DoclingServeClient.java      | 292 ++++++++++++++++++++-
 .../component/docling/DoclingServeProducerIT.java  | 108 ++++++++
 12 files changed, 829 insertions(+), 29 deletions(-)

diff --git 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java
 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java
index 270856eb5ef8..8162ee261074 100644
--- 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java
+++ 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java
@@ -32,6 +32,12 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": 
getOrCreateConfiguration(target).setApiKeyHeader(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "apitimeout":
+        case "apiTimeout": 
getOrCreateConfiguration(target).setApiTimeout(property(camelContext, 
long.class, value)); return true;
+        case "asyncpollinterval":
+        case "asyncPollInterval": 
getOrCreateConfiguration(target).setAsyncPollInterval(property(camelContext, 
long.class, value)); return true;
+        case "asynctimeout":
+        case "asyncTimeout": 
getOrCreateConfiguration(target).setAsyncTimeout(property(camelContext, 
long.class, value)); return true;
         case "authenticationscheme":
         case "authenticationScheme": 
getOrCreateConfiguration(target).setAuthenticationScheme(property(camelContext, 
org.apache.camel.component.docling.AuthenticationScheme.class, value)); return 
true;
         case "authenticationtoken":
@@ -62,6 +68,8 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "outputFormat": 
getOrCreateConfiguration(target).setOutputFormat(property(camelContext, 
java.lang.String.class, value)); return true;
         case "processtimeout":
         case "processTimeout": 
getOrCreateConfiguration(target).setProcessTimeout(property(camelContext, 
long.class, value)); return true;
+        case "useasyncmode":
+        case "useAsyncMode": 
getOrCreateConfiguration(target).setUseAsyncMode(property(camelContext, 
boolean.class, value)); return true;
         case "usedoclingserve":
         case "useDoclingServe": 
getOrCreateConfiguration(target).setUseDoclingServe(property(camelContext, 
boolean.class, value)); return true;
         case "workingdirectory":
@@ -75,6 +83,12 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return java.lang.String.class;
+        case "apitimeout":
+        case "apiTimeout": return long.class;
+        case "asyncpollinterval":
+        case "asyncPollInterval": return long.class;
+        case "asynctimeout":
+        case "asyncTimeout": return long.class;
         case "authenticationscheme":
         case "authenticationScheme": return 
org.apache.camel.component.docling.AuthenticationScheme.class;
         case "authenticationtoken":
@@ -105,6 +119,8 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "outputFormat": return java.lang.String.class;
         case "processtimeout":
         case "processTimeout": return long.class;
+        case "useasyncmode":
+        case "useAsyncMode": return boolean.class;
         case "usedoclingserve":
         case "useDoclingServe": return boolean.class;
         case "workingdirectory":
@@ -119,6 +135,12 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return 
getOrCreateConfiguration(target).getApiKeyHeader();
+        case "apitimeout":
+        case "apiTimeout": return 
getOrCreateConfiguration(target).getApiTimeout();
+        case "asyncpollinterval":
+        case "asyncPollInterval": return 
getOrCreateConfiguration(target).getAsyncPollInterval();
+        case "asynctimeout":
+        case "asyncTimeout": return 
getOrCreateConfiguration(target).getAsyncTimeout();
         case "authenticationscheme":
         case "authenticationScheme": return 
getOrCreateConfiguration(target).getAuthenticationScheme();
         case "authenticationtoken":
@@ -149,6 +171,8 @@ public class DoclingComponentConfigurer extends 
PropertyConfigurerSupport implem
         case "outputFormat": return 
getOrCreateConfiguration(target).getOutputFormat();
         case "processtimeout":
         case "processTimeout": return 
getOrCreateConfiguration(target).getProcessTimeout();
+        case "useasyncmode":
+        case "useAsyncMode": return 
getOrCreateConfiguration(target).isUseAsyncMode();
         case "usedoclingserve":
         case "useDoclingServe": return 
getOrCreateConfiguration(target).isUseDoclingServe();
         case "workingdirectory":
diff --git 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java
 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java
index 585af1165493..b9ad1b2c73f5 100644
--- 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java
+++ 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java
@@ -25,6 +25,12 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": target.setApiKeyHeader(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "apitimeout":
+        case "apiTimeout": target.setApiTimeout(property(camelContext, 
long.class, value)); return true;
+        case "asyncpollinterval":
+        case "asyncPollInterval": 
target.setAsyncPollInterval(property(camelContext, long.class, value)); return 
true;
+        case "asynctimeout":
+        case "asyncTimeout": target.setAsyncTimeout(property(camelContext, 
long.class, value)); return true;
         case "authenticationscheme":
         case "authenticationScheme": 
target.setAuthenticationScheme(property(camelContext, 
org.apache.camel.component.docling.AuthenticationScheme.class, value)); return 
true;
         case "authenticationtoken":
@@ -50,6 +56,8 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         case "outputFormat": target.setOutputFormat(property(camelContext, 
java.lang.String.class, value)); return true;
         case "processtimeout":
         case "processTimeout": target.setProcessTimeout(property(camelContext, 
long.class, value)); return true;
+        case "useasyncmode":
+        case "useAsyncMode": target.setUseAsyncMode(property(camelContext, 
boolean.class, value)); return true;
         case "usedoclingserve":
         case "useDoclingServe": 
target.setUseDoclingServe(property(camelContext, boolean.class, value)); return 
true;
         case "workingdirectory":
@@ -63,6 +71,12 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return java.lang.String.class;
+        case "apitimeout":
+        case "apiTimeout": return long.class;
+        case "asyncpollinterval":
+        case "asyncPollInterval": return long.class;
+        case "asynctimeout":
+        case "asyncTimeout": return long.class;
         case "authenticationscheme":
         case "authenticationScheme": return 
org.apache.camel.component.docling.AuthenticationScheme.class;
         case "authenticationtoken":
@@ -88,6 +102,8 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         case "outputFormat": return java.lang.String.class;
         case "processtimeout":
         case "processTimeout": return long.class;
+        case "useasyncmode":
+        case "useAsyncMode": return boolean.class;
         case "usedoclingserve":
         case "useDoclingServe": return boolean.class;
         case "workingdirectory":
@@ -102,6 +118,12 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return target.getApiKeyHeader();
+        case "apitimeout":
+        case "apiTimeout": return target.getApiTimeout();
+        case "asyncpollinterval":
+        case "asyncPollInterval": return target.getAsyncPollInterval();
+        case "asynctimeout":
+        case "asyncTimeout": return target.getAsyncTimeout();
         case "authenticationscheme":
         case "authenticationScheme": return target.getAuthenticationScheme();
         case "authenticationtoken":
@@ -127,6 +149,8 @@ public class DoclingConfigurationConfigurer extends 
org.apache.camel.support.com
         case "outputFormat": return target.getOutputFormat();
         case "processtimeout":
         case "processTimeout": return target.getProcessTimeout();
+        case "useasyncmode":
+        case "useAsyncMode": return target.isUseAsyncMode();
         case "usedoclingserve":
         case "useDoclingServe": return target.isUseDoclingServe();
         case "workingdirectory":
diff --git 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java
 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java
index 88e14d5862c2..633d25a55840 100644
--- 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java
+++ 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java
@@ -25,6 +25,12 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": 
target.getConfiguration().setApiKeyHeader(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "apitimeout":
+        case "apiTimeout": 
target.getConfiguration().setApiTimeout(property(camelContext, long.class, 
value)); return true;
+        case "asyncpollinterval":
+        case "asyncPollInterval": 
target.getConfiguration().setAsyncPollInterval(property(camelContext, 
long.class, value)); return true;
+        case "asynctimeout":
+        case "asyncTimeout": 
target.getConfiguration().setAsyncTimeout(property(camelContext, long.class, 
value)); return true;
         case "authenticationscheme":
         case "authenticationScheme": 
target.getConfiguration().setAuthenticationScheme(property(camelContext, 
org.apache.camel.component.docling.AuthenticationScheme.class, value)); return 
true;
         case "authenticationtoken":
@@ -52,6 +58,8 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         case "outputFormat": 
target.getConfiguration().setOutputFormat(property(camelContext, 
java.lang.String.class, value)); return true;
         case "processtimeout":
         case "processTimeout": 
target.getConfiguration().setProcessTimeout(property(camelContext, long.class, 
value)); return true;
+        case "useasyncmode":
+        case "useAsyncMode": 
target.getConfiguration().setUseAsyncMode(property(camelContext, boolean.class, 
value)); return true;
         case "usedoclingserve":
         case "useDoclingServe": 
target.getConfiguration().setUseDoclingServe(property(camelContext, 
boolean.class, value)); return true;
         case "workingdirectory":
@@ -65,6 +73,12 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return java.lang.String.class;
+        case "apitimeout":
+        case "apiTimeout": return long.class;
+        case "asyncpollinterval":
+        case "asyncPollInterval": return long.class;
+        case "asynctimeout":
+        case "asyncTimeout": return long.class;
         case "authenticationscheme":
         case "authenticationScheme": return 
org.apache.camel.component.docling.AuthenticationScheme.class;
         case "authenticationtoken":
@@ -92,6 +106,8 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         case "outputFormat": return java.lang.String.class;
         case "processtimeout":
         case "processTimeout": return long.class;
+        case "useasyncmode":
+        case "useAsyncMode": return boolean.class;
         case "usedoclingserve":
         case "useDoclingServe": return boolean.class;
         case "workingdirectory":
@@ -106,6 +122,12 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "apikeyheader":
         case "apiKeyHeader": return 
target.getConfiguration().getApiKeyHeader();
+        case "apitimeout":
+        case "apiTimeout": return target.getConfiguration().getApiTimeout();
+        case "asyncpollinterval":
+        case "asyncPollInterval": return 
target.getConfiguration().getAsyncPollInterval();
+        case "asynctimeout":
+        case "asyncTimeout": return 
target.getConfiguration().getAsyncTimeout();
         case "authenticationscheme":
         case "authenticationScheme": return 
target.getConfiguration().getAuthenticationScheme();
         case "authenticationtoken":
@@ -133,6 +155,8 @@ public class DoclingEndpointConfigurer extends 
PropertyConfigurerSupport impleme
         case "outputFormat": return 
target.getConfiguration().getOutputFormat();
         case "processtimeout":
         case "processTimeout": return 
target.getConfiguration().getProcessTimeout();
+        case "useasyncmode":
+        case "useAsyncMode": return target.getConfiguration().isUseAsyncMode();
         case "usedoclingserve":
         case "useDoclingServe": return 
target.getConfiguration().isUseDoclingServe();
         case "workingdirectory":
diff --git 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java
 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java
index 257c975eafa8..7ab76504c522 100644
--- 
a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java
+++ 
b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java
@@ -23,8 +23,11 @@ public class DoclingEndpointUriFactory extends 
org.apache.camel.support.componen
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(18);
+        Set<String> props = new HashSet<>(22);
         props.add("apiKeyHeader");
+        props.add("apiTimeout");
+        props.add("asyncPollInterval");
+        props.add("asyncTimeout");
         props.add("authenticationScheme");
         props.add("authenticationToken");
         props.add("contentInBody");
@@ -40,6 +43,7 @@ public class DoclingEndpointUriFactory extends 
org.apache.camel.support.componen
         props.add("operationId");
         props.add("outputFormat");
         props.add("processTimeout");
+        props.add("useAsyncMode");
         props.add("useDoclingServe");
         props.add("workingDirectory");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
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 c04a0fe85843..f402df50e1e7 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
@@ -34,15 +34,19 @@
     "operation": { "index": 7, "kind": "property", "displayName": "Operation", 
"group": "producer", "label": "", "required": true, "type": "enum", "javaType": 
"org.apache.camel.component.docling.DoclingOperations", "enum": [ 
"CONVERT_TO_MARKDOWN", "CONVERT_TO_HTML", "CONVERT_TO_JSON", "EXTRACT_TEXT", 
"EXTRACT_STRUCTURED_DATA" ], "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": "CONVERT_TO_MARKDOWN", 
"configurationClass": "org.apache.camel.c [...]
     "outputFormat": { "index": 8, "kind": "property", "displayName": "Output 
Format", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": "markdown", 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Output format for 
document conversion" },
     "useDoclingServe": { "index": 9, "kind": "property", "displayName": "Use 
Docling Serve", "group": "producer", "label": "", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Use docling-serve API 
instead of CLI command" },
-    "autowiredEnabled": { "index": 10, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
-    "convertEndpoint": { "index": 11, "kind": "property", "displayName": 
"Convert Endpoint", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"\/v1\/convert\/source", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Docling-serve API 
convert endp [...]
-    "doclingCommand": { "index": 12, "kind": "property", "displayName": 
"Docling Command", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Path to Docling Python 
executable or command" },
-    "processTimeout": { "index": 13, "kind": "property", "displayName": 
"Process Timeout", "group": "advanced", "label": "advanced", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 30000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Timeout for Docling 
process execution in milliseconds" },
-    "workingDirectory": { "index": 14, "kind": "property", "displayName": 
"Working Directory", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Working directory for 
Docling execution" },
-    "apiKeyHeader": { "index": 15, "kind": "property", "displayName": "Api Key 
Header", "group": "security", "label": "security", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"X-API-Key", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Header name for API key 
authentication" },
-    "authenticationScheme": { "index": 16, "kind": "property", "displayName": 
"Authentication Scheme", "group": "security", "label": "security", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", 
"BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "NONE", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", "configuration [...]
-    "authenticationToken": { "index": 17, "kind": "property", "displayName": 
"Authentication Token", "group": "security", "label": "security", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Authentication token for 
docling-serve API (Bearer token or API  [...]
-    "maxFileSize": { "index": 18, "kind": "property", "displayName": "Max File 
Size", "group": "security", "label": "security", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 52428800, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum file size in 
bytes for processing" }
+    "apiTimeout": { "index": 10, "kind": "property", "displayName": "Api 
Timeout", "group": "advanced", "label": "advanced", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 60000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "API request timeout in 
milliseconds" },
+    "asyncPollInterval": { "index": 11, "kind": "property", "displayName": 
"Async Poll Interval", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "long", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
2000, "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Polling interval for 
async conversion status in millise [...]
+    "asyncTimeout": { "index": 12, "kind": "property", "displayName": "Async 
Timeout", "group": "advanced", "label": "advanced", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 300000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum time to wait for 
async conversion completion in millisec [...]
+    "autowiredEnabled": { "index": 13, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching  [...]
+    "convertEndpoint": { "index": 14, "kind": "property", "displayName": 
"Convert Endpoint", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"\/v1\/convert\/source", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Docling-serve API 
convert endp [...]
+    "doclingCommand": { "index": 15, "kind": "property", "displayName": 
"Docling Command", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Path to Docling Python 
executable or command" },
+    "processTimeout": { "index": 16, "kind": "property", "displayName": 
"Process Timeout", "group": "advanced", "label": "advanced", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 30000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Timeout for Docling 
process execution in milliseconds" },
+    "useAsyncMode": { "index": 17, "kind": "property", "displayName": "Use 
Async Mode", "group": "advanced", "label": "advanced", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Use asynchronous 
conversion mode (docling-serve API only)" },
+    "workingDirectory": { "index": 18, "kind": "property", "displayName": 
"Working Directory", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Working directory for 
Docling execution" },
+    "apiKeyHeader": { "index": 19, "kind": "property", "displayName": "Api Key 
Header", "group": "security", "label": "security", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"X-API-Key", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Header name for API key 
authentication" },
+    "authenticationScheme": { "index": 20, "kind": "property", "displayName": 
"Authentication Scheme", "group": "security", "label": "security", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", 
"BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "NONE", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", "configuration [...]
+    "authenticationToken": { "index": 21, "kind": "property", "displayName": 
"Authentication Token", "group": "security", "label": "security", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Authentication token for 
docling-serve API (Bearer token or API  [...]
+    "maxFileSize": { "index": 22, "kind": "property", "displayName": "Max File 
Size", "group": "security", "label": "security", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 52428800, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum file size in 
bytes for processing" }
   },
   "headers": {
     "CamelDoclingOperation": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"DoclingOperations", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The operation to perform", 
"constantName": "org.apache.camel.component.docling.DoclingHeaders#OPERATION" },
@@ -52,7 +56,11 @@
     "CamelDoclingProcessingOptions": { "index": 4, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Map<String, Object>", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Additional processing 
options", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#PROCESSING_OPTIONS" },
     "CamelDoclingEnableOCR": { "index": 5, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Whether to include OCR processing", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#ENABLE_OCR" },
     "CamelDoclingOCRLanguage": { "index": 6, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Language for OCR processing", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#OCR_LANGUAGE" },
-    "CamelDoclingCustomArguments": { "index": 7, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<String>", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Custom command line 
arguments to pass to Docling", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CUSTOM_ARGUMENTS" }
+    "CamelDoclingCustomArguments": { "index": 7, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "List<String>", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "Custom command line 
arguments to pass to Docling", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#CUSTOM_ARGUMENTS" },
+    "CamelDoclingUseAsyncMode": { "index": 8, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Use asynchronous conversion mode (overrides endpoint 
configuration)", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#USE_ASYNC_MODE" },
+    "CamelDoclingAsyncPollInterval": { "index": 9, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Polling interval for async conversion 
status in milliseconds", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#ASYNC_POLL_INTERVAL" },
+    "CamelDoclingAsyncTimeout": { "index": 10, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Maximum time to wait for async 
conversion completion in milliseconds", "constantName": 
"org.apache.camel.component.docling.DoclingHeaders#ASYNC_TIMEOUT" },
+    "CamelDoclingTaskId": { "index": 11, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Task ID for checking async conversion status", 
"constantName": "org.apache.camel.component.docling.DoclingHeaders#TASK_ID" }
   },
   "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" 
},
@@ -65,13 +73,17 @@
     "outputFormat": { "index": 7, "kind": "parameter", "displayName": "Output 
Format", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": "markdown", 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Output format for 
document conversion" },
     "useDoclingServe": { "index": 8, "kind": "parameter", "displayName": "Use 
Docling Serve", "group": "producer", "label": "", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Use docling-serve API 
instead of CLI command" },
     "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
-    "convertEndpoint": { "index": 10, "kind": "parameter", "displayName": 
"Convert Endpoint", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"\/v1\/convert\/source", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Docling-serve API 
convert end [...]
-    "doclingCommand": { "index": 11, "kind": "parameter", "displayName": 
"Docling Command", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Path to Docling Python 
executable or command" },
-    "processTimeout": { "index": 12, "kind": "parameter", "displayName": 
"Process Timeout", "group": "advanced", "label": "advanced", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 30000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Timeout for Docling 
process execution in milliseconds" },
-    "workingDirectory": { "index": 13, "kind": "parameter", "displayName": 
"Working Directory", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Working directory for 
Docling execution" },
-    "apiKeyHeader": { "index": 14, "kind": "parameter", "displayName": "Api 
Key Header", "group": "security", "label": "security", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"X-API-Key", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Header name for API key 
authentication" },
-    "authenticationScheme": { "index": 15, "kind": "parameter", "displayName": 
"Authentication Scheme", "group": "security", "label": "security", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", 
"BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "NONE", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", "configuratio [...]
-    "authenticationToken": { "index": 16, "kind": "parameter", "displayName": 
"Authentication Token", "group": "security", "label": "security", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Authentication token for 
docling-serve API (Bearer token or API [...]
-    "maxFileSize": { "index": 17, "kind": "parameter", "displayName": "Max 
File Size", "group": "security", "label": "security", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 52428800, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum file size in 
bytes for processing" }
+    "apiTimeout": { "index": 10, "kind": "parameter", "displayName": "Api 
Timeout", "group": "advanced", "label": "advanced", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 60000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "API request timeout in 
milliseconds" },
+    "asyncPollInterval": { "index": 11, "kind": "parameter", "displayName": 
"Async Poll Interval", "group": "advanced", "label": "advanced", "required": 
false, "type": "integer", "javaType": "long", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
2000, "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Polling interval for 
async conversion status in millis [...]
+    "asyncTimeout": { "index": 12, "kind": "parameter", "displayName": "Async 
Timeout", "group": "advanced", "label": "advanced", "required": false, "type": 
"integer", "javaType": "long", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "defaultValue": 300000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum time to wait for 
async conversion completion in millise [...]
+    "convertEndpoint": { "index": 13, "kind": "parameter", "displayName": 
"Convert Endpoint", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"\/v1\/convert\/source", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Docling-serve API 
convert end [...]
+    "doclingCommand": { "index": 14, "kind": "parameter", "displayName": 
"Docling Command", "group": "advanced", "label": "advanced", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Path to Docling Python 
executable or command" },
+    "processTimeout": { "index": 15, "kind": "parameter", "displayName": 
"Process Timeout", "group": "advanced", "label": "advanced", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 30000, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Timeout for Docling 
process execution in milliseconds" },
+    "useAsyncMode": { "index": 16, "kind": "parameter", "displayName": "Use 
Async Mode", "group": "advanced", "label": "advanced", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
false, "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Use asynchronous 
conversion mode (docling-serve API only)" },
+    "workingDirectory": { "index": 17, "kind": "parameter", "displayName": 
"Working Directory", "group": "advanced", "label": "advanced", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Working directory for 
Docling execution" },
+    "apiKeyHeader": { "index": 18, "kind": "parameter", "displayName": "Api 
Key Header", "group": "security", "label": "security", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"X-API-Key", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Header name for API key 
authentication" },
+    "authenticationScheme": { "index": 19, "kind": "parameter", "displayName": 
"Authentication Scheme", "group": "security", "label": "security", "required": 
false, "type": "enum", "javaType": 
"org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", 
"BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "NONE", "configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", "configuratio [...]
+    "authenticationToken": { "index": 20, "kind": "parameter", "displayName": 
"Authentication Token", "group": "security", "label": "security", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": true, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Authentication token for 
docling-serve API (Bearer token or API [...]
+    "maxFileSize": { "index": 21, "kind": "parameter", "displayName": "Max 
File Size", "group": "security", "label": "security", "required": false, 
"type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 52428800, 
"configurationClass": 
"org.apache.camel.component.docling.DoclingConfiguration", 
"configurationField": "configuration", "description": "Maximum file size in 
bytes for processing" }
   }
 }
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 fb2a9d4cb4a9..f2121f71cece 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
@@ -459,6 +459,142 @@ public class CustomArgsBean {
 }
 ----
 
+== Asynchronous Processing
+
+The component supports asynchronous document conversion when using 
docling-serve API mode. This is particularly useful for:
+- Large documents that take a long time to process
+- High-volume batch processing scenarios
+- Better resource utilization on the server side
+
+=== Enabling Async Mode
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("file:///data/documents?include=.*\\.pdf")
+    .to("docling:CONVERT_TO_MARKDOWN?" +
+        "useDoclingServe=true&" +
+        "useAsyncMode=true&" +
+        "asyncPollInterval=2000&" +
+        "asyncTimeout=300000&" +
+        "contentInBody=true")
+    .to("file:///data/output");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: "file:///data/documents"
+      parameters:
+        include: ".*\\.pdf"
+    steps:
+      - to:
+          uri: "docling:CONVERT_TO_MARKDOWN"
+          parameters:
+            useDoclingServe: true
+            useAsyncMode: true
+            asyncPollInterval: 2000
+            asyncTimeout: 300000
+            contentInBody: true
+      - to:
+          uri: "file:///data/output"
+----
+====
+
+=== Async Processing with Custom Timeout
+
+For very large documents, you may need to increase the timeout:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("file:///data/large-documents?include=.*\\.pdf")
+    .to("docling:CONVERT_TO_MARKDOWN?" +
+        "useDoclingServe=true&" +
+        "useAsyncMode=true&" +
+        "asyncPollInterval=5000&" +
+        "asyncTimeout=600000&" +  // 10 minutes
+        "contentInBody=true")
+    .to("file:///data/output");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: "file:///data/large-documents"
+      parameters:
+        include: ".*\\.pdf"
+    steps:
+      - to:
+          uri: "docling:CONVERT_TO_MARKDOWN"
+          parameters:
+            useDoclingServe: true
+            useAsyncMode: true
+            asyncPollInterval: 5000
+            asyncTimeout: 600000
+            contentInBody: true
+      - to:
+          uri: "file:///data/output"
+----
+====
+
+=== Using Headers to Control Async Behavior
+
+You can override async settings per-message using headers:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("file:///data/documents?include=.*\\.pdf")
+    .process(exchange -> {
+        File file = exchange.getIn().getBody(File.class);
+        // Use async mode only for large files
+        if (file.length() > 10 * 1024 * 1024) { // > 10MB
+            exchange.getIn().setHeader("CamelDoclingUseAsyncMode", true);
+            exchange.getIn().setHeader("CamelDoclingAsyncTimeout", 600000L);
+        }
+    })
+    .to("docling:CONVERT_TO_MARKDOWN?useDoclingServe=true&contentInBody=true")
+    .to("file:///data/output");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: "file:///data/documents"
+      parameters:
+        include: ".*\\.pdf"
+    steps:
+      - process:
+          ref: "asyncDecisionProcessor"
+      - to:
+          uri: "docling:CONVERT_TO_MARKDOWN"
+          parameters:
+            useDoclingServe: true
+            contentInBody: true
+      - to:
+          uri: "file:///data/output"
+----
+====
+
 == Using Docling-Serve API
 
 === Basic usage with docling-serve
@@ -773,5 +909,8 @@ The component handles various error scenarios:
 - Consider using `contentInBody=true` when using docling-serve API mode to get 
results directly in the body
 - The `maxFileSize` setting helps prevent resource exhaustion
 - **API Mode vs CLI Mode**: The docling-serve API mode typically offers better 
performance and resource utilization for high-volume document processing, as it 
maintains a persistent server instance
+- **Async Mode**: For large documents or high-volume processing, enable 
`useAsyncMode=true` to prevent blocking the Camel thread pool. The component 
will poll the docling-serve API for completion status while freeing up 
processing threads
+- **Async Configuration**: Adjust `asyncPollInterval` (default 2000ms) and 
`asyncTimeout` (default 300000ms/5 minutes) based on your document size and 
processing requirements
+- **Batch Processing**: When processing multiple documents, async mode allows 
better parallelization as the docling-serve instance can process multiple 
documents concurrently while Camel polls for results
 
 include::spring-boot:partial$starter.adoc[]
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/ConversionStatus.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/ConversionStatus.java
new file mode 100644
index 000000000000..f5a1e8d03b44
--- /dev/null
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/ConversionStatus.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.docling;
+
+/**
+ * Represents the status of an async document conversion task.
+ */
+public class ConversionStatus {
+
+    public enum Status {
+        PENDING,
+        IN_PROGRESS,
+        COMPLETED,
+        FAILED,
+        UNKNOWN
+    }
+
+    private final String taskId;
+    private final Status status;
+    private final String result;
+    private final String errorMessage;
+    private final Integer progress;
+
+    public ConversionStatus(String taskId, Status status) {
+        this(taskId, status, null, null, null);
+    }
+
+    public ConversionStatus(String taskId, Status status, String result, 
String errorMessage, Integer progress) {
+        this.taskId = taskId;
+        this.status = status;
+        this.result = result;
+        this.errorMessage = errorMessage;
+        this.progress = progress;
+    }
+
+    public String getTaskId() {
+        return taskId;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public Integer getProgress() {
+        return progress;
+    }
+
+    public boolean isCompleted() {
+        return status == Status.COMPLETED;
+    }
+
+    public boolean isFailed() {
+        return status == Status.FAILED;
+    }
+
+    public boolean isInProgress() {
+        return status == Status.IN_PROGRESS || status == Status.PENDING;
+    }
+
+    @Override
+    public String toString() {
+        return "ConversionStatus{" +
+               "taskId='" + taskId + '\'' +
+               ", status=" + status +
+               ", progress=" + progress +
+               ", errorMessage='" + errorMessage + '\'' +
+               '}';
+    }
+}
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java
index b0bc2418e708..600f958a7220 100644
--- 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java
@@ -98,6 +98,22 @@ public class DoclingConfiguration implements Cloneable {
     @Metadata(description = "Docling-serve API convert endpoint path", 
defaultValue = "/v1/convert/source")
     private String convertEndpoint = "/v1/convert/source";
 
+    @UriParam(label = "advanced")
+    @Metadata(description = "Use asynchronous conversion mode (docling-serve 
API only)", defaultValue = "false")
+    private boolean useAsyncMode = false;
+
+    @UriParam(label = "advanced")
+    @Metadata(description = "Polling interval for async conversion status in 
milliseconds", defaultValue = "2000")
+    private long asyncPollInterval = 2000;
+
+    @UriParam(label = "advanced")
+    @Metadata(description = "Maximum time to wait for async conversion 
completion in milliseconds", defaultValue = "300000")
+    private long asyncTimeout = 300000; // 5 minutes
+
+    @UriParam(label = "advanced")
+    @Metadata(description = "API request timeout in milliseconds", 
defaultValue = "60000")
+    private long apiTimeout = 60000;
+
     public DoclingOperations getOperation() {
         return operation;
     }
@@ -226,6 +242,38 @@ public class DoclingConfiguration implements Cloneable {
         this.convertEndpoint = convertEndpoint;
     }
 
+    public boolean isUseAsyncMode() {
+        return useAsyncMode;
+    }
+
+    public void setUseAsyncMode(boolean useAsyncMode) {
+        this.useAsyncMode = useAsyncMode;
+    }
+
+    public long getAsyncPollInterval() {
+        return asyncPollInterval;
+    }
+
+    public void setAsyncPollInterval(long asyncPollInterval) {
+        this.asyncPollInterval = asyncPollInterval;
+    }
+
+    public long getAsyncTimeout() {
+        return asyncTimeout;
+    }
+
+    public void setAsyncTimeout(long asyncTimeout) {
+        this.asyncTimeout = asyncTimeout;
+    }
+
+    public long getApiTimeout() {
+        return apiTimeout;
+    }
+
+    public void setApiTimeout(long apiTimeout) {
+        this.apiTimeout = apiTimeout;
+    }
+
     public DoclingConfiguration copy() {
         try {
             return (DoclingConfiguration) super.clone();
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 f8f96c9b8c26..74aa88afe9a0 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
@@ -44,6 +44,18 @@ public final class DoclingHeaders {
     @Metadata(description = "Custom command line arguments to pass to 
Docling", javaType = "List<String>")
     public static final String CUSTOM_ARGUMENTS = 
"CamelDoclingCustomArguments";
 
+    @Metadata(description = "Use asynchronous conversion mode (overrides 
endpoint configuration)", javaType = "Boolean")
+    public static final String USE_ASYNC_MODE = "CamelDoclingUseAsyncMode";
+
+    @Metadata(description = "Polling interval for async conversion status in 
milliseconds", javaType = "Long")
+    public static final String ASYNC_POLL_INTERVAL = 
"CamelDoclingAsyncPollInterval";
+
+    @Metadata(description = "Maximum time to wait for async conversion 
completion in milliseconds", javaType = "Long")
+    public static final String ASYNC_TIMEOUT = "CamelDoclingAsyncTimeout";
+
+    @Metadata(description = "Task ID for checking async conversion status", 
javaType = "String")
+    public static final String TASK_ID = "CamelDoclingTaskId";
+
     private DoclingHeaders() {
     }
 
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 3a440b7d349d..a15bcf01c8d2 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
@@ -59,11 +59,14 @@ public class DoclingProducer extends DefaultProducer {
                     configuration.getAuthenticationScheme(),
                     configuration.getAuthenticationToken(),
                     configuration.getApiKeyHeader(),
-                    configuration.getConvertEndpoint());
-            LOG.info("DoclingProducer configured to use docling-serve API at: 
{}{} with authentication: {}",
+                    configuration.getConvertEndpoint(),
+                    configuration.getAsyncPollInterval(),
+                    configuration.getAsyncTimeout());
+            LOG.info("DoclingProducer configured to use docling-serve API at: 
{}{} with authentication: {} (async mode: {})",
                     configuration.getDoclingServeUrl(),
                     configuration.getConvertEndpoint(),
-                    configuration.getAuthenticationScheme());
+                    configuration.getAuthenticationScheme(),
+                    configuration.isUseAsyncMode());
         } else {
             LOG.info("DoclingProducer configured to use docling CLI command");
         }
@@ -117,7 +120,7 @@ public class DoclingProducer extends DefaultProducer {
         LOG.debug("DoclingProducer converting to markdown");
         if (configuration.isUseDoclingServe()) {
             String inputPath = getInputPath(exchange);
-            String result = doclingServeClient.convertDocument(inputPath, 
"markdown");
+            String result = convertUsingDoclingServe(inputPath, "markdown", 
exchange);
             exchange.getIn().setBody(result);
         } else {
             String inputPath = getInputPath(exchange);
@@ -129,7 +132,7 @@ public class DoclingProducer extends DefaultProducer {
         LOG.debug("DoclingProducer converting to HTML");
         if (configuration.isUseDoclingServe()) {
             String inputPath = getInputPath(exchange);
-            String result = doclingServeClient.convertDocument(inputPath, 
"html");
+            String result = convertUsingDoclingServe(inputPath, "html", 
exchange);
             exchange.getIn().setBody(result);
         } else {
             String inputPath = getInputPath(exchange);
@@ -140,7 +143,7 @@ public class DoclingProducer extends DefaultProducer {
     private void processConvertToJSON(Exchange exchange) throws Exception {
         if (configuration.isUseDoclingServe()) {
             String inputPath = getInputPath(exchange);
-            String result = doclingServeClient.convertDocument(inputPath, 
"json");
+            String result = convertUsingDoclingServe(inputPath, "json", 
exchange);
             exchange.getIn().setBody(result);
         } else {
             String inputPath = getInputPath(exchange);
@@ -151,7 +154,7 @@ public class DoclingProducer extends DefaultProducer {
     private void processExtractText(Exchange exchange) throws Exception {
         if (configuration.isUseDoclingServe()) {
             String inputPath = getInputPath(exchange);
-            String result = doclingServeClient.convertDocument(inputPath, 
"text");
+            String result = convertUsingDoclingServe(inputPath, "text", 
exchange);
             exchange.getIn().setBody(result);
         } else {
             String inputPath = getInputPath(exchange);
@@ -162,7 +165,7 @@ public class DoclingProducer extends DefaultProducer {
     private void processExtractStructuredData(Exchange exchange) throws 
Exception {
         if (configuration.isUseDoclingServe()) {
             String inputPath = getInputPath(exchange);
-            String result = doclingServeClient.convertDocument(inputPath, 
"json");
+            String result = convertUsingDoclingServe(inputPath, "json", 
exchange);
             exchange.getIn().setBody(result);
         } else {
             String inputPath = getInputPath(exchange);
@@ -170,6 +173,29 @@ public class DoclingProducer extends DefaultProducer {
         }
     }
 
+    private String convertUsingDoclingServe(String inputPath, String 
outputFormat) throws Exception {
+        return convertUsingDoclingServe(inputPath, outputFormat, null);
+    }
+
+    private String convertUsingDoclingServe(String inputPath, String 
outputFormat, Exchange exchange) throws Exception {
+        // Check for header override
+        boolean useAsync = configuration.isUseAsyncMode();
+        if (exchange != null) {
+            Boolean asyncModeHeader = 
exchange.getIn().getHeader(DoclingHeaders.USE_ASYNC_MODE, Boolean.class);
+            if (asyncModeHeader != null) {
+                useAsync = asyncModeHeader;
+            }
+        }
+
+        if (useAsync) {
+            LOG.debug("Using async mode for conversion");
+            return doclingServeClient.convertDocumentAsyncAndWait(inputPath, 
outputFormat);
+        } else {
+            LOG.debug("Using sync mode for conversion");
+            return doclingServeClient.convertDocument(inputPath, outputFormat);
+        }
+    }
+
     private String getInputPath(Exchange exchange) throws 
InvalidPayloadException, IOException {
         String inputPath = 
exchange.getIn().getHeader(DoclingHeaders.INPUT_FILE_PATH, String.class);
 
diff --git 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java
 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java
index 9da6af787708..615c5fac6ea6 100644
--- 
a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java
+++ 
b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
@@ -43,6 +44,7 @@ public class DoclingServeClient {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(DoclingServeClient.class);
     private static final String DEFAULT_CONVERT_ENDPOINT = 
"/v1/convert/source";
+    private static final String DEFAULT_ASYNC_CONVERT_ENDPOINT = 
"/v1/convert/source/async";
 
     private final String baseUrl;
     private final ObjectMapper objectMapper;
@@ -51,20 +53,28 @@ public class DoclingServeClient {
     private final String authenticationToken;
     private final String apiKeyHeader;
     private final String convertEndpoint;
+    private final long asyncPollInterval;
+    private final long asyncTimeout;
 
     public DoclingServeClient(String baseUrl) {
-        this(baseUrl, AuthenticationScheme.NONE, null, "X-API-Key", 
DEFAULT_CONVERT_ENDPOINT);
+        this(baseUrl, AuthenticationScheme.NONE, null, "X-API-Key", 
DEFAULT_CONVERT_ENDPOINT, 2000, 300000);
     }
 
     public DoclingServeClient(
                               String baseUrl, AuthenticationScheme 
authenticationScheme, String authenticationToken,
                               String apiKeyHeader) {
-        this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, 
DEFAULT_CONVERT_ENDPOINT);
+        this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, 
DEFAULT_CONVERT_ENDPOINT, 2000, 300000);
     }
 
     public DoclingServeClient(
                               String baseUrl, AuthenticationScheme 
authenticationScheme, String authenticationToken,
                               String apiKeyHeader, String convertEndpoint) {
+        this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, 
convertEndpoint, 2000, 300000);
+    }
+
+    public DoclingServeClient(
+                              String baseUrl, AuthenticationScheme 
authenticationScheme, String authenticationToken,
+                              String apiKeyHeader, String convertEndpoint, 
long asyncPollInterval, long asyncTimeout) {
         this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, 
baseUrl.length() - 1) : baseUrl;
         this.objectMapper = new ObjectMapper();
         this.httpClient = HttpClients.createDefault();
@@ -72,6 +82,8 @@ public class DoclingServeClient {
         this.authenticationToken = authenticationToken;
         this.apiKeyHeader = apiKeyHeader != null ? apiKeyHeader : "X-API-Key";
         this.convertEndpoint = convertEndpoint != null ? convertEndpoint : 
DEFAULT_CONVERT_ENDPOINT;
+        this.asyncPollInterval = asyncPollInterval;
+        this.asyncTimeout = asyncTimeout;
     }
 
     /**
@@ -267,6 +279,282 @@ public class DoclingServeClient {
         }
     }
 
+    /**
+     * Apply authentication headers to the HTTP GET request based on the 
configured authentication scheme.
+     *
+     * @param httpGet The HTTP GET request to add authentication to
+     */
+    private void applyAuthenticationGet(HttpGet httpGet) {
+        if (authenticationScheme == null || authenticationScheme == 
AuthenticationScheme.NONE) {
+            return;
+        }
+
+        if (authenticationToken == null || authenticationToken.isEmpty()) {
+            LOG.warn("Authentication scheme is set to {} but no authentication 
token provided", authenticationScheme);
+            return;
+        }
+
+        switch (authenticationScheme) {
+            case BEARER:
+                httpGet.setHeader("Authorization", "Bearer " + 
authenticationToken);
+                LOG.debug("Applied Bearer token authentication");
+                break;
+            case API_KEY:
+                httpGet.setHeader(apiKeyHeader, authenticationToken);
+                LOG.debug("Applied API Key authentication with header: {}", 
apiKeyHeader);
+                break;
+            default:
+                LOG.warn("Unknown authentication scheme: {}", 
authenticationScheme);
+        }
+    }
+
+    /**
+     * Convert a document using the docling-serve async API and return the 
task ID.
+     *
+     * @param  inputSource  File path or URL to the document
+     * @param  outputFormat Output format (md, json, html, text)
+     * @return              Task ID for the async conversion
+     * @throws IOException  If the API call fails
+     */
+    public String convertDocumentAsync(String inputSource, String 
outputFormat) throws IOException {
+        LOG.debug("Starting async document conversion using docling-serve API: 
{}", inputSource);
+
+        String asyncEndpoint = convertEndpoint.replace("/v1/convert/source", 
DEFAULT_ASYNC_CONVERT_ENDPOINT);
+
+        // Check if input is a URL or file path
+        Map<String, Object> requestBody = buildRequestBody(inputSource, 
outputFormat);
+
+        String jsonRequest = objectMapper.writeValueAsString(requestBody);
+        LOG.debug("Async request body: {}", jsonRequest);
+
+        HttpPost httpPost = new HttpPost(baseUrl + asyncEndpoint);
+        httpPost.setEntity(new StringEntity(jsonRequest, 
ContentType.APPLICATION_JSON));
+        httpPost.setHeader("Accept", "application/json");
+        applyAuthentication(httpPost);
+
+        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+            int statusCode = response.getCode();
+            String responseBody;
+            try {
+                responseBody = EntityUtils.toString(response.getEntity());
+            } catch (org.apache.hc.core5.http.ParseException e) {
+                throw new IOException("Failed to parse response from 
docling-serve API", e);
+            }
+
+            if (statusCode >= 200 && statusCode < 300) {
+                // Extract task ID from response
+                JsonNode rootNode = objectMapper.readTree(responseBody);
+                if (rootNode.has("task_id")) {
+                    return rootNode.get("task_id").asText();
+                } else if (rootNode.has("id")) {
+                    return rootNode.get("id").asText();
+                } else {
+                    throw new IOException("No task ID found in async 
conversion response: " + responseBody);
+                }
+            } else {
+                throw new IOException(
+                        "Docling-serve async API request failed with status " 
+ statusCode + ": " + responseBody);
+            }
+        }
+    }
+
+    /**
+     * Check the status of an async conversion task.
+     *
+     * @param  taskId      The task ID returned from convertDocumentAsync
+     * @return             ConversionStatus object with current status
+     * @throws IOException If the API call fails
+     */
+    public ConversionStatus checkConversionStatus(String taskId) throws 
IOException {
+        LOG.debug("Checking status for task: {}", taskId);
+
+        String statusEndpoint = "/v1/status/poll/" + taskId;
+        HttpGet httpGet = new HttpGet(baseUrl + statusEndpoint);
+        httpGet.setHeader("Accept", "application/json");
+        applyAuthenticationGet(httpGet);
+
+        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+            int statusCode = response.getCode();
+            String responseBody;
+            try {
+                responseBody = EntityUtils.toString(response.getEntity());
+            } catch (org.apache.hc.core5.http.ParseException e) {
+                throw new IOException("Failed to parse response from 
docling-serve API", e);
+            }
+
+            if (statusCode >= 200 && statusCode < 300) {
+                JsonNode rootNode = objectMapper.readTree(responseBody);
+                return parseConversionStatus(taskId, rootNode);
+            } else {
+                throw new IOException(
+                        "Failed to check task status. Status code: " + 
statusCode + ", Response: " + responseBody);
+            }
+        }
+    }
+
+    /**
+     * Convert a document asynchronously and wait for completion by polling.
+     *
+     * @param  inputSource  File path or URL to the document
+     * @param  outputFormat Output format (md, json, html, text)
+     * @return              Converted document content
+     * @throws IOException  If the API call fails or timeout occurs
+     */
+    public String convertDocumentAsyncAndWait(String inputSource, String 
outputFormat) throws IOException {
+        String taskId = convertDocumentAsync(inputSource, outputFormat);
+        LOG.debug("Started async conversion with task ID: {}", taskId);
+
+        long startTime = System.currentTimeMillis();
+        long deadline = startTime + asyncTimeout;
+
+        while (System.currentTimeMillis() < deadline) {
+            ConversionStatus status = checkConversionStatus(taskId);
+            LOG.debug("Task {} status: {}", taskId, status.getStatus());
+
+            if (status.isCompleted()) {
+                LOG.debug("Task {} completed successfully", taskId);
+                return status.getResult();
+            } else if (status.isFailed()) {
+                throw new IOException("Async conversion failed: " + 
status.getErrorMessage());
+            }
+
+            // Wait before next poll
+            try {
+                Thread.sleep(asyncPollInterval);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                throw new IOException("Async conversion interrupted", e);
+            }
+        }
+
+        throw new IOException(
+                "Async conversion timed out after " + asyncTimeout + "ms for 
task: " + taskId);
+    }
+
+    private Map<String, Object> buildRequestBody(String inputSource, String 
outputFormat) {
+        Map<String, Object> requestBody = new HashMap<>();
+
+        if (inputSource.startsWith("http://";) || 
inputSource.startsWith("https://";)) {
+            Map<String, String> source = new HashMap<>();
+            source.put("kind", "http");
+            source.put("url", inputSource);
+            requestBody.put("sources", Collections.singletonList(source));
+        } else {
+            try {
+                File file = new File(inputSource);
+                byte[] fileBytes = Files.readAllBytes(file.toPath());
+                String base64Content = 
Base64.getEncoder().encodeToString(fileBytes);
+
+                Map<String, String> source = new HashMap<>();
+                source.put("kind", "file");
+                source.put("base64_string", base64Content);
+                source.put("filename", file.getName());
+                requestBody.put("sources", Collections.singletonList(source));
+            } catch (IOException e) {
+                throw new RuntimeException("Failed to read file: " + 
inputSource, e);
+            }
+        }
+
+        // Add output format if specified
+        if (outputFormat != null && !outputFormat.isEmpty()) {
+            Map<String, Object> options = new HashMap<>();
+            options.put("to_formats", 
Collections.singletonList(mapOutputFormat(outputFormat)));
+            requestBody.put("options", options);
+        }
+
+        return requestBody;
+    }
+
+    private ConversionStatus parseConversionStatus(String taskId, JsonNode 
statusNode) {
+        // Docling-serve uses "task_status" field with values: pending, 
started, success, failure
+        String statusStr = statusNode.has("task_status") ? 
statusNode.get("task_status").asText() : "unknown";
+        ConversionStatus.Status status;
+
+        switch (statusStr.toLowerCase()) {
+            case "pending":
+                status = ConversionStatus.Status.PENDING;
+                break;
+            case "started":
+            case "in_progress":
+            case "running":
+            case "processing":
+                status = ConversionStatus.Status.IN_PROGRESS;
+                break;
+            case "success":
+            case "completed":
+                status = ConversionStatus.Status.COMPLETED;
+                break;
+            case "failure":
+            case "failed":
+            case "error":
+                status = ConversionStatus.Status.FAILED;
+                break;
+            default:
+                LOG.warn("Unknown task status: {}", statusStr);
+                status = ConversionStatus.Status.UNKNOWN;
+        }
+
+        String result = null;
+        String errorMessage = null;
+
+        // For completed tasks, fetch the result
+        if (status == ConversionStatus.Status.COMPLETED) {
+            try {
+                result = fetchTaskResult(taskId);
+            } catch (IOException e) {
+                LOG.warn("Failed to fetch result for completed task: {}", 
taskId, e);
+            }
+        }
+
+        // For failed tasks, extract error message
+        if (status == ConversionStatus.Status.FAILED) {
+            if (statusNode.has("task_meta") && 
statusNode.get("task_meta").has("error")) {
+                errorMessage = 
statusNode.get("task_meta").get("error").asText();
+            } else if (statusNode.has("error")) {
+                errorMessage = statusNode.get("error").asText();
+            } else {
+                errorMessage = "Task failed without error message";
+            }
+        }
+
+        Integer progress = statusNode.has("task_position") ? 
statusNode.get("task_position").asInt() : null;
+
+        return new ConversionStatus(taskId, status, result, errorMessage, 
progress);
+    }
+
+    /**
+     * Fetch the result of a completed async conversion task.
+     *
+     * @param  taskId      The task ID
+     * @return             Converted document content
+     * @throws IOException If the API call fails
+     */
+    private String fetchTaskResult(String taskId) throws IOException {
+        LOG.debug("Fetching result for task: {}", taskId);
+
+        String resultEndpoint = "/v1/result/" + taskId;
+        HttpGet httpGet = new HttpGet(baseUrl + resultEndpoint);
+        httpGet.setHeader("Accept", "application/json");
+        applyAuthenticationGet(httpGet);
+
+        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+            int statusCode = response.getCode();
+            String responseBody;
+            try {
+                responseBody = EntityUtils.toString(response.getEntity());
+            } catch (org.apache.hc.core5.http.ParseException e) {
+                throw new IOException("Failed to parse response from 
docling-serve API", e);
+            }
+
+            if (statusCode >= 200 && statusCode < 300) {
+                return extractConvertedContent(responseBody, null);
+            } else {
+                throw new IOException(
+                        "Failed to fetch task result. Status code: " + 
statusCode + ", Response: " + responseBody);
+            }
+        }
+    }
+
     public void close() throws IOException {
         if (httpClient != null) {
             httpClient.close();
diff --git 
a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java
 
b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java
index a713e72806f1..9d12251b2b0f 100644
--- 
a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java
+++ 
b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java
@@ -144,6 +144,97 @@ public class DoclingServeProducerIT extends 
CamelTestSupport {
         LOG.info("Output file size: {} bytes", outputFile.length());
     }
 
+    @Test
+    public void testAsyncMarkdownConversion() throws Exception {
+        Path testFile = createTestFile();
+
+        String result = 
template.requestBodyAndHeader("direct:convert-async-markdown",
+                testFile.toString(),
+                DoclingHeaders.INPUT_FILE_PATH, testFile.toString(), 
String.class);
+
+        assertNotNull(result, "Async conversion result should not be null");
+        assertTrue(result.length() > 0, "Async conversion result should not be 
empty");
+
+        LOG.info("Successfully converted document to Markdown using async 
mode");
+    }
+
+    @Test
+    public void testAsyncHtmlConversion() throws Exception {
+        Path testFile = createTestFile();
+
+        String result = 
template.requestBodyAndHeader("direct:convert-async-html",
+                testFile.toString(),
+                DoclingHeaders.OPERATION, DoclingOperations.CONVERT_TO_HTML, 
String.class);
+
+        assertNotNull(result, "Async HTML conversion result should not be 
null");
+        assertTrue(result.length() > 0, "Async HTML conversion result should 
not be empty");
+
+        LOG.info("Successfully converted document to HTML using async mode");
+    }
+
+    @Test
+    public void testAsyncJsonConversion() throws Exception {
+        Path testFile = createTestFile();
+
+        String result = 
template.requestBodyAndHeader("direct:convert-async-json",
+                testFile.toString(),
+                DoclingHeaders.INPUT_FILE_PATH, testFile.toString(), 
String.class);
+
+        assertNotNull(result, "Async JSON conversion result should not be 
null");
+        assertTrue(result.length() > 0, "Async JSON conversion result should 
not be empty");
+        assertTrue(result.contains("{") || result.contains("["), "JSON result 
should contain JSON structure");
+
+        LOG.info("Successfully converted document to JSON using async mode");
+    }
+
+    @Test
+    public void testAsyncUrlConversion() throws Exception {
+        String url = "https://arxiv.org/pdf/2501.17887";;
+
+        String result = template.requestBody("direct:convert-async-url", url, 
String.class);
+
+        assertNotNull(result, "Async URL conversion result should not be 
null");
+        assertTrue(result.length() > 0, "Async URL conversion result should 
not be empty");
+
+        LOG.info("Successfully converted document from URL using async mode");
+    }
+
+    @Test
+    public void testAsyncConversionWithCustomTimeout() throws Exception {
+        Path testFile = createTestFile();
+
+        String result = 
template.requestBodyAndHeader("direct:convert-async-custom-timeout",
+                testFile.toString(),
+                DoclingHeaders.INPUT_FILE_PATH, testFile.toString(), 
String.class);
+
+        assertNotNull(result, "Async conversion with custom timeout should not 
be null");
+        assertTrue(result.length() > 0, "Async conversion with custom timeout 
should not be empty");
+
+        LOG.info("Successfully converted document using async mode with custom 
timeout");
+    }
+
+    @Test
+    public void testAsyncConversionWithHeaderOverride() throws Exception {
+        Path testFile = createTestFile();
+
+        // Use sync endpoint but override with async header
+        String result = 
template.requestBodyAndHeaders("direct:convert-markdown-serve",
+                testFile.toString(),
+                new java.util.HashMap<String, Object>() {
+                    {
+                        put(DoclingHeaders.INPUT_FILE_PATH, 
testFile.toString());
+                        put(DoclingHeaders.USE_ASYNC_MODE, true);
+                        put(DoclingHeaders.ASYNC_POLL_INTERVAL, 1000L);
+                        put(DoclingHeaders.ASYNC_TIMEOUT, 120000L);
+                    }
+                }, String.class);
+
+        assertNotNull(result, "Async conversion via header override should not 
be null");
+        assertTrue(result.length() > 0, "Async conversion via header override 
should not be empty");
+
+        LOG.info("Successfully converted document using async mode via header 
override");
+    }
+
     private Path createTestFile() throws Exception {
         Path tempFile = Files.createTempFile("docling-serve-test", ".md");
         Files.write(tempFile,
@@ -157,6 +248,7 @@ public class DoclingServeProducerIT extends 
CamelTestSupport {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
+                // Synchronous conversion routes
                 from("direct:convert-markdown-serve")
                         
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true");
 
@@ -172,6 +264,22 @@ public class DoclingServeProducerIT extends 
CamelTestSupport {
                 from("direct:convert-and-write")
                         
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true")
                         .to("file:" + outputDir.toString() + 
"?fileName=converted-output.md");
+
+                // Asynchronous conversion routes
+                from("direct:convert-async-markdown")
+                        
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true&useAsyncMode=true&asyncPollInterval=1000&asyncTimeout=120000");
+
+                from("direct:convert-async-html")
+                        
.to("docling:convert?operation=CONVERT_TO_HTML&contentInBody=true&useAsyncMode=true&asyncPollInterval=1000&asyncTimeout=120000");
+
+                from("direct:convert-async-json")
+                        
.to("docling:convert?operation=CONVERT_TO_JSON&contentInBody=true&useAsyncMode=true&asyncPollInterval=1000&asyncTimeout=120000");
+
+                from("direct:convert-async-url")
+                        
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true&useAsyncMode=true&asyncPollInterval=1000&asyncTimeout=120000");
+
+                from("direct:convert-async-custom-timeout")
+                        
.to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true&useAsyncMode=true&asyncPollInterval=500&asyncTimeout=300000");
             }
         };
     }

Reply via email to