This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.18.x by this push:
new aa644a2a0364 [camel-4.18.x] CAMEL-26282: camel-flowable - xml inbound
channels parse events with the Camel XML settings (#29170)
aa644a2a0364 is described below
commit aa644a2a03645fe35b315a2a78620ce7e1f87ca7
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Nov 4 14:25:12 2026 +0100
[camel-4.18.x] CAMEL-26282: camel-flowable - xml inbound channels parse
events with the Camel XML settings (#29170)
An inbound channel of type camel with the xml deserializer type and no
deserializerDelegateExpression now parses the event with
CamelStringToXmlDocumentDeserializer instead of the Flowable 7
StringToXmlDocumentDeserializer, which uses the JDK default parser
settings. The Camel deserializer does not load external DTDs, does not
include external general or parameter entities, keeps entity references
as nodes and does not process XInclude, as Flowable 8 does, and turns on
secure processing. A custom deserializer is kept as it is.
Adds a section to the component documentation and a note to the 4.18.6
upgrade guide.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
(cherry picked from commit 03ed6ff1a3a19d98384ba95b2b30ac488e84fb51)
---
.../src/main/docs/flowable-component.adoc | 10 ++
.../CamelStringToXmlDocumentDeserializer.java | 87 ++++++++++++++++
.../camel/component/flowable/FlowableProducer.java | 22 ++++
.../CamelStringToXmlDocumentDeserializerTest.java | 64 ++++++++++++
.../flowable/FlowableInboundXmlChannelTest.java | 114 +++++++++++++++++++++
.../test/resources/channel/userXmlChannel.channel | 11 ++
.../src/test/resources/event/userXmlEvent.event | 14 +++
.../src/test/resources/process/startXml.bpmn20.xml | 44 ++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_18.adoc | 9 ++
9 files changed, 375 insertions(+)
diff --git a/components/camel-flowable/src/main/docs/flowable-component.adoc
b/components/camel-flowable/src/main/docs/flowable-component.adoc
index da314865be77..0ec35e4d27d6 100644
--- a/components/camel-flowable/src/main/docs/flowable-component.adoc
+++ b/components/camel-flowable/src/main/docs/flowable-component.adoc
@@ -37,6 +37,16 @@ include::partial$component-endpoint-headers.adoc[]
The body content is defined by the event model deployed to the Flowable Event
Registry.
The event message can then be mapped to process or case variables in the
process BPMN or case CMMN model.
+=== XML events
+
+For an inbound channel of type `camel` with `deserializerType` set to `xml`,
the producer parses the event with the XML
+parser settings that Camel uses, which are also the settings of Flowable 8:
external DTDs are not loaded, external
+general and parameter entities are not included, entity references are kept as
entity reference nodes, and XInclude
+is not processed.
+
+To parse the event in another way, set `deserializerDelegateExpression` in the
channel model to your own
+`InboundEventDeserializer`. The producer keeps a custom deserializer as it is.
+
=== Sending to a channel that is not deployed yet
A route that sends to `flowable:channelKey` can start before the inbound
channel model with that key is deployed
diff --git
a/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializer.java
b/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializer.java
new file mode 100644
index 000000000000..375aecc61b85
--- /dev/null
+++
b/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializer.java
@@ -0,0 +1,87 @@
+/*
+ * 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.flowable;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+
+import org.flowable.common.engine.api.FlowableException;
+import
org.flowable.eventregistry.impl.serialization.StringToXmlDocumentDeserializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Deserializes the event of an inbound channel with the xml deserializer type
into a {@link Document}.
+ * <p/>
+ * The parser does not load external DTDs, does not include external general
or parameter entities, does not expand
+ * entity references and does not process XInclude, which are the settings
Flowable 8 uses for this deserializer (the
+ * Flowable 7 deserializer leaves them at the JDK defaults). Secure processing
is turned on, and access to external DTDs
+ * and schemas is restricted, as in the other XML parsing of Camel.
+ */
+public class CamelStringToXmlDocumentDeserializer extends
StringToXmlDocumentDeserializer {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(CamelStringToXmlDocumentDeserializer.class);
+
+ @Override
+ public Document deserialize(Object rawEvent) {
+ try {
+ DocumentBuilder documentBuilder =
createDocumentBuilderFactory().newDocumentBuilder();
+ try (InputStream inputStream = new
ByteArrayInputStream(convertEventToBytes(rawEvent))) {
+ return documentBuilder.parse(inputStream);
+ }
+ } catch (Exception e) {
+ throw new FlowableException("Could not deserialize event to xml",
e);
+ }
+ }
+
+ protected DocumentBuilderFactory createDocumentBuilderFactory() {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setExpandEntityReferences(false);
+ factory.setXIncludeAware(false);
+ setFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setFeature(factory,
"http://xml.org/sax/features/external-general-entities", false);
+ setFeature(factory,
"http://xml.org/sax/features/external-parameter-entities", false);
+ setFeature(factory,
"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ setFeature(factory,
"http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
+ setAttribute(factory, XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ setAttribute(factory, XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+ return factory;
+ }
+
+ private static void setFeature(DocumentBuilderFactory factory, String
feature, boolean value) {
+ try {
+ factory.setFeature(feature, value);
+ } catch (ParserConfigurationException e) {
+ LOG.debug("DocumentBuilderFactory does not support the feature {}
with value {}", feature, value, e);
+ }
+ }
+
+ private static void setAttribute(DocumentBuilderFactory factory, String
attribute, String value) {
+ try {
+ factory.setAttribute(attribute, value);
+ } catch (IllegalArgumentException e) {
+ LOG.debug("DocumentBuilderFactory does not support the attribute
{}", attribute, e);
+ }
+ }
+}
diff --git
a/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/FlowableProducer.java
b/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/FlowableProducer.java
index d73d7e8d98f2..2ef90844e529 100644
---
a/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/FlowableProducer.java
+++
b/components/camel-flowable/src/main/java/org/apache/camel/component/flowable/FlowableProducer.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.component.flowable;
+import org.w3c.dom.Document;
+
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
@@ -23,10 +25,14 @@ import org.apache.camel.support.DefaultProducer;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.eventregistry.impl.DefaultInboundEvent;
import org.flowable.eventregistry.impl.EventRegistryEngineConfiguration;
+import
org.flowable.eventregistry.impl.pipeline.DefaultInboundEventProcessingPipeline;
+import
org.flowable.eventregistry.impl.serialization.StringToXmlDocumentDeserializer;
import org.flowable.eventregistry.model.CamelInboundChannelModel;
public class FlowableProducer extends DefaultProducer {
+ private static final CamelStringToXmlDocumentDeserializer XML_DESERIALIZER
= new CamelStringToXmlDocumentDeserializer();
+
protected CamelInboundChannelModel camelInboundChannel;
protected EventRegistryEngineConfiguration
eventRegistryEngineConfiguration;
@@ -50,11 +56,27 @@ public class FlowableProducer extends DefaultProducer {
configuration = deployed.getEventRegistryEngineConfiguration();
}
+ useCamelXmlDeserializer(channel);
+
Message message = exchange.getMessage();
DefaultInboundEvent inboundEvent = new
DefaultInboundEvent(message.getBody(), message.getHeaders());
configuration.getEventRegistry().eventReceived(channel, inboundEvent);
}
+ /**
+ * An inbound channel with the xml deserializer type and no
deserializerDelegateExpression gets the default xml
+ * deserializer of Flowable. Use the Camel one instead, which parses with
the XML settings Camel uses. A custom
+ * deserializer is kept as it is.
+ */
+ @SuppressWarnings("unchecked")
+ private static void useCamelXmlDeserializer(CamelInboundChannelModel
channel) {
+ if (channel.getInboundEventProcessingPipeline() instanceof
DefaultInboundEventProcessingPipeline<?> pipeline
+ && pipeline.getInboundEventDeserializer() != null
+ && pipeline.getInboundEventDeserializer().getClass() ==
StringToXmlDocumentDeserializer.class) {
+ ((DefaultInboundEventProcessingPipeline<Document>)
pipeline).setInboundEventDeserializer(XML_DESERIALIZER);
+ }
+ }
+
private FlowableEndpoint lookupDeployedEndpoint() {
Endpoint endpoint =
getEndpoint().getCamelContext().hasEndpoint(getEndpoint().getEndpointUri());
if (endpoint instanceof FlowableEndpoint flowableEndpoint &&
flowableEndpoint.getCamelInboundChannel() != null
diff --git
a/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializerTest.java
b/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializerTest.java
new file mode 100644
index 000000000000..b3a05a31eace
--- /dev/null
+++
b/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/CamelStringToXmlDocumentDeserializerTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.flowable;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.w3c.dom.Document;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class CamelStringToXmlDocumentDeserializerTest {
+
+ private final CamelStringToXmlDocumentDeserializer deserializer = new
CamelStringToXmlDocumentDeserializer();
+
+ @Test
+ public void xmlEventIsDeserialized() {
+ Document document = deserializer.deserialize("<user><name>John
Doe</name><age>23</age></user>");
+
+ assertEquals("user", document.getDocumentElement().getNodeName());
+ assertEquals("John Doe",
document.getElementsByTagName("name").item(0).getTextContent());
+ }
+
+ @Test
+ public void entityDeclaredInDoctypeIsNotExpandedFromFile() throws
Exception {
+ Path file = Path.of("target", "flowable-xml-deserializer",
"entity.txt").toAbsolutePath();
+ Files.createDirectories(file.getParent());
+ Files.writeString(file, "content-of-the-entity-file",
StandardCharsets.UTF_8);
+
+ Document document = deserializer.deserialize(
+ "<?xml version=\"1.0\"?><!DOCTYPE user [<!ENTITY content
SYSTEM \"" + file.toUri() + "\">]>"
+ +
"<user><name>&content;</name></user>");
+
+
assertFalse(document.getDocumentElement().getTextContent().contains("content-of-the-entity-file"));
+ }
+
+ @Test
+ public void externalDtdIsNotLoaded() {
+ Path missing = Path.of("target", "flowable-xml-deserializer",
"missing.dtd").toAbsolutePath();
+
+ Document document = deserializer.deserialize(
+ "<?xml version=\"1.0\"?><!DOCTYPE user SYSTEM \"" +
missing.toUri() + "\"><user><name>John Doe</name></user>");
+
+ assertEquals("John Doe",
document.getElementsByTagName("name").item(0).getTextContent());
+ }
+}
diff --git
a/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/FlowableInboundXmlChannelTest.java
b/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/FlowableInboundXmlChannelTest.java
new file mode 100644
index 000000000000..063e86092b01
--- /dev/null
+++
b/components/camel-flowable/src/test/java/org/apache/camel/component/flowable/FlowableInboundXmlChannelTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.flowable;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.w3c.dom.Document;
+
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.eventregistry.api.InboundEventDeserializer;
+import
org.flowable.eventregistry.impl.pipeline.DefaultInboundEventProcessingPipeline;
+import
org.flowable.eventregistry.impl.serialization.StringToXmlDocumentDeserializer;
+import org.flowable.eventregistry.model.CamelInboundChannelModel;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class FlowableInboundXmlChannelTest extends CamelFlowableTestCase {
+
+ private String processDeploymentId;
+
+ @BeforeEach
+ public void deployEventRegistryModels() {
+
eventRegistryEngineConfiguration.getEventRepositoryService().createDeployment()
+ .addClasspathResource("channel/userXmlChannel.channel")
+ .addClasspathResource("event/userXmlEvent.event")
+ .deploy();
+ processDeploymentId =
deployProcessDefinition("process/startXml.bpmn20.xml");
+ }
+
+ @AfterEach
+ public void deleteProcessDeployment() {
+ repositoryService.deleteDeployment(processDeploymentId, true);
+ }
+
+ @Test
+ public void xmlEventStartsProcessWithMappedVariables() {
+ template.sendBody("direct:startXml", "<user><name>John
Doe</name><age>23</age></user>");
+
+ ProcessInstance processInstance = startedProcessInstance();
+ assertEquals("John Doe",
runtimeService.getVariable(processInstance.getId(), "name"));
+ assertEquals(23, runtimeService.getVariable(processInstance.getId(),
"age"));
+ }
+
+ @Test
+ public void xmlChannelUsesCamelXmlDeserializer() {
+ template.sendBody("direct:startXml", "<user><name>John
Doe</name><age>23</age></user>");
+
+ assertInstanceOf(CamelStringToXmlDocumentDeserializer.class,
xmlPipeline().getInboundEventDeserializer());
+ }
+
+ @Test
+ public void customXmlDeserializerIsKept() {
+ InboundEventDeserializer<Document> custom = new
StringToXmlDocumentDeserializer() {
+ };
+ xmlPipeline().setInboundEventDeserializer(custom);
+
+ template.sendBody("direct:startXml", "<user><name>John
Doe</name><age>23</age></user>");
+
+ assertSame(custom, xmlPipeline().getInboundEventDeserializer());
+ assertEquals("John Doe",
runtimeService.getVariable(startedProcessInstance().getId(), "name"));
+ }
+
+ @Test
+ public void entityDeclaredInDoctypeIsNotExpandedFromFile() throws
Exception {
+ Path file = Path.of("target", "flowable-xml-channel",
"entity.txt").toAbsolutePath();
+ Files.createDirectories(file.getParent());
+ Files.writeString(file, "content-of-the-entity-file",
StandardCharsets.UTF_8);
+
+ template.sendBody("direct:startXml",
+ "<?xml version=\"1.0\"?><!DOCTYPE event [<!ENTITY content
SYSTEM \"" + file.toUri() + "\">]>"
+ + "<name>&content;</name>");
+
+ Object name =
runtimeService.getVariable(startedProcessInstance().getId(), "name");
+ assertFalse(name != null &&
name.toString().contains("content-of-the-entity-file"),
+ "The entity declared in the DOCTYPE must not be expanded from
the file, but the variable is: " + name);
+ }
+
+ private ProcessInstance startedProcessInstance() {
+ ProcessInstance processInstance
+ =
runtimeService.createProcessInstanceQuery().processDefinitionKey("camelXmlProcess").singleResult();
+ assertNotNull(processInstance);
+ return processInstance;
+ }
+
+ @SuppressWarnings("unchecked")
+ private DefaultInboundEventProcessingPipeline<Document> xmlPipeline() {
+ CamelInboundChannelModel channel
+ = context.getEndpoint("flowable:userXmlChannel",
FlowableEndpoint.class).getCamelInboundChannel();
+ return (DefaultInboundEventProcessingPipeline<Document>)
channel.getInboundEventProcessingPipeline();
+ }
+}
diff --git
a/components/camel-flowable/src/test/resources/channel/userXmlChannel.channel
b/components/camel-flowable/src/test/resources/channel/userXmlChannel.channel
new file mode 100644
index 000000000000..242b6cd3b301
--- /dev/null
+++
b/components/camel-flowable/src/test/resources/channel/userXmlChannel.channel
@@ -0,0 +1,11 @@
+{
+ "name": "Camel user xml channel",
+ "key": "userXmlChannel",
+ "channelType": "inbound",
+ "type": "camel",
+ "sourceUri": "direct:startXml",
+ "deserializerType": "xml",
+ "channelEventKeyDetection": {
+ "fixedValue": "userXmlEvent"
+ }
+}
diff --git
a/components/camel-flowable/src/test/resources/event/userXmlEvent.event
b/components/camel-flowable/src/test/resources/event/userXmlEvent.event
new file mode 100644
index 000000000000..53ed6ae3518b
--- /dev/null
+++ b/components/camel-flowable/src/test/resources/event/userXmlEvent.event
@@ -0,0 +1,14 @@
+{
+ "key": "userXmlEvent",
+ "name": "User Xml Event",
+ "payload": [
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "age",
+ "type": "integer"
+ }
+ ]
+}
diff --git
a/components/camel-flowable/src/test/resources/process/startXml.bpmn20.xml
b/components/camel-flowable/src/test/resources/process/startXml.bpmn20.xml
new file mode 100644
index 000000000000..0b0054983673
--- /dev/null
+++ b/components/camel-flowable/src/test/resources/process/startXml.bpmn20.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:flowable="http://flowable.org/bpmn"
+ targetNamespace="Examples"
+ xmlns:tns="Examples">
+
+ <process id="camelXmlProcess">
+
+ <startEvent id="theStart">
+ <extensionElements>
+ <flowable:eventType>userXmlEvent</flowable:eventType>
+ <flowable:eventOutParameter source="name" target="name" />
+ <flowable:eventOutParameter source="age" target="age" />
+ </extensionElements>
+ </startEvent>
+
+ <sequenceFlow id="flow1" sourceRef="theStart" targetRef="userTask"/>
+
+ <userTask id="userTask" />
+ <sequenceFlow id="flow2" sourceRef="userTask" targetRef="end" />
+
+ <endEvent id="end" />
+
+ </process>
+
+</definitions>
\ No newline at end of file
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
index bfe17f833ef4..db2a6adae36c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc
@@ -227,6 +227,15 @@ auto-mock names, tracing and metrics are the same as
before.
Two routes that consume from the same address with different endpoint options
are no longer rejected at startup as
"Multiple consumers for the same endpoint is not allowed". Use one consumer
per address.
+=== camel-flowable - xml inbound channels parse the event with the Camel XML
settings
+
+The `flowable` producer now parses the event of an inbound channel of type
`camel` with `deserializerType` set to
+`xml` with the XML parser settings that Camel uses, which are also the
settings of Flowable 8: external DTDs are not
+loaded, external general and parameter entities are not included, entity
references are kept as entity reference
+nodes, and XInclude is not processed. Before, the Flowable 7 deserializer
parsed the event with the JDK defaults.
+An event that relies on an external DTD or an external entity no longer gets
their content. A channel that sets
+`deserializerDelegateExpression` keeps its own deserializer, which can parse
such events.
+
== Upgrading from 4.18.4 to 4.18.5
=== camel-docling - output path handling