This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new ef973877aec6 CAMEL-26499: camel-smooks - convert a remote file to a
Smooks Source, set the execution context header on a bean route with a
correlation id (#28977)
ef973877aec6 is described below
commit ef973877aec6e52ce0a8842d6af41362d0c15a44
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Nov 2 21:48:41 2026 +0100
CAMEL-26499: camel-smooks - convert a remote file to a Smooks Source, set
the execution context header on a bean route with a correlation id (#28977)
… set the execution context header on a bean route with a correlation id
The WrappedFile to Smooks Source type converter cast the body of the file to
java.io.File, so a remote file (ftp, sftp, ftps) failed with a
ClassCastException. A java.io.File is now read from its URL and a remote
file
from its downloaded content, like SmooksProcessor does since CAMEL-26062.
A bean route with a correlation id now also sets the
CamelSmooksExecutionContext header, like a bean route without one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../smooks/converter/SourceConverterLoader.java | 2 +-
.../smooks/converter/SourceConverter.java | 23 ++++++++++-----
.../camel/component/smooks/routing/BeanRouter.java | 1 +
.../component/smooks/SmooksReaderBodyTest.java | 33 ++++++++++++++++++++--
.../component/smooks/routing/BeanRouterTest.java | 15 ++++++++++
5 files changed, 63 insertions(+), 11 deletions(-)
diff --git
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
index f726e2646f92..13f3c4c7a301 100644
---
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
+++
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/converter/SourceConverterLoader.java
@@ -46,7 +46,7 @@ public final class SourceConverterLoader implements
TypeConverterLoader, CamelCo
private void registerConverters(TypeConverterRegistry registry) {
addTypeConverter(registry, org.smooks.api.io.Source.class,
org.apache.camel.WrappedFile.class, false,
(type, exchange, value) -> {
- Object answer =
org.apache.camel.component.smooks.converter.SourceConverter.toURISource((org.apache.camel.WrappedFile)
value);
+ Object answer =
org.apache.camel.component.smooks.converter.SourceConverter.toURISource((org.apache.camel.WrappedFile)
value, exchange);
if (false && answer == null) {
answer = Void.class;
}
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
index d7be0730a751..eeb1226557c1 100644
---
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
+++
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/converter/SourceConverter.java
@@ -19,9 +19,10 @@ package org.apache.camel.component.smooks.converter;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
-import java.net.URI;
import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.WrappedFile;
import org.smooks.api.SmooksException;
import org.smooks.api.io.Source;
@@ -68,12 +69,20 @@ public class SourceConverter {
}
@Converter
- public static Source toURISource(WrappedFile<File> genericFile) {
- String systemId = new javax.xml.transform.stream.StreamSource((File)
genericFile.getBody()).getSystemId();
- try {
- return new URLSource(URI.create(systemId).toURL());
- } catch (MalformedURLException e) {
- throw new SmooksException(e);
+ public static Source toURISource(WrappedFile<?> wrappedFile, Exchange
exchange) throws NoTypeConversionAvailableException {
+ if (wrappedFile.getFile() instanceof File file) {
+ try {
+ return new URLSource(file.toURI().toURL());
+ } catch (MalformedURLException e) {
+ throw new SmooksException(e);
+ }
}
+ if (exchange == null) {
+ // the content of a remote file can only be loaded with an exchange
+ return null;
+ }
+ // A remote file (ftp, sftp, ftps) is not a java.io.File: read its
downloaded content
+ return new StreamSource<>(
+
exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class,
exchange, wrappedFile));
}
}
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/routing/BeanRouter.java
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/routing/BeanRouter.java
index 2d29e1f585a2..ff8432dbb32d 100644
---
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/routing/BeanRouter.java
+++
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/routing/BeanRouter.java
@@ -173,6 +173,7 @@ public class BeanRouter implements AfterVisitor, Consumer,
PreExecutionLifecycle
Processor processor = exchange -> {
Message in = exchange.getIn();
in.setBody(bean);
+ in.setHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT,
executionContext);
in.setHeader(correlationIdName.orElse(null),
correlationIdPattern.get().apply(FreeMarkerUtils.getMergedModel(executionContext)));
};
diff --git
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksReaderBodyTest.java
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksReaderBodyTest.java
index 85e504837779..19b8d97f057b 100644
---
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksReaderBodyTest.java
+++
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksReaderBodyTest.java
@@ -41,6 +41,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.smooks.Smooks;
+import org.smooks.api.io.Source;
import org.smooks.io.payload.Export;
import org.smooks.io.payload.Exports;
import org.smooks.io.sink.JavaSink;
@@ -54,8 +55,8 @@ import static
org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
- * Message bodies that are a {@link SAXSource}, a file or a remote file are
read by the reader of the Smooks
- * configuration.
+ * Message bodies that are a {@link SAXSource}, a file or a remote file (also
when converted to a Smooks {@link Source}
+ * first) are read by the reader of the Smooks configuration.
*/
class SmooksReaderBodyTest extends CamelTestSupport {
@@ -135,6 +136,25 @@ class SmooksReaderBodyTest extends CamelTestSupport {
assertOrderXml(remoteFile);
}
+ @Test
+ void localFileConvertedToSourceIsReadByTheConfiguredReader() throws
Exception {
+ // The file consumer sets the java.io.File as the file and as the body
+ File file = writeOrder().toFile();
+ GenericFile<File> localFile = new GenericFile<>();
+ localFile.setFile(file);
+ localFile.setBody(file);
+ assertOrderXml("direct:ediSource", localFile);
+ }
+
+ @Test
+ void remoteFileConvertedToSourceIsReadByTheConfiguredReader() {
+ GenericFile<Object> remoteFile = new GenericFile<>();
+ remoteFile.setFile(new Object());
+ remoteFile.setFileName("order.txt");
+ remoteFile.setBody(orderEdi.getBytes(StandardCharsets.UTF_8));
+ assertOrderXml("direct:ediSource", remoteFile);
+ }
+
@Test
void severalExportsAreReturnedInTheOrderOfTheirSinkType() {
// Smooks creates the sinks in no fixed order, so send several times
@@ -151,7 +171,11 @@ class SmooksReaderBodyTest extends CamelTestSupport {
}
private void assertOrderXml(Object body) {
- String xml = template.requestBody("direct:edi", body, String.class);
+ assertOrderXml("direct:edi", body);
+ }
+
+ private void assertOrderXml(String endpointUri, Object body) {
+ String xml = template.requestBody(endpointUri, body, String.class);
assertFalse(DiffBuilder.compare(expectedOrderXml).withTest(xml).ignoreComments().ignoreWhitespace().build()
.hasDifferences(), xml);
}
@@ -165,6 +189,9 @@ class SmooksReaderBodyTest extends CamelTestSupport {
public void configure() {
// Without stream caching, as it would turn a SAXSource body
into a String before Smooks reads it
from("direct:edi").noStreamCaching().to("smooks://edi-to-xml-smooks-config.xml");
+ // The body is converted to a Smooks Source by the type
converter before Smooks reads it
+
from("direct:ediSource").noStreamCaching().convertBodyTo(Source.class)
+ .to("smooks://edi-to-xml-smooks-config.xml");
from("direct:customer").noStreamCaching().to("smooks://smooks-config.xml");
from("direct:severalExports")
.process(new SmooksProcessor(
diff --git
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/routing/BeanRouterTest.java
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/routing/BeanRouterTest.java
index 75f00ac4479f..10e6864f7c9c 100644
---
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/routing/BeanRouterTest.java
+++
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/routing/BeanRouterTest.java
@@ -95,6 +95,21 @@ public class BeanRouterTest extends CamelTestSupport {
assertInstanceOf(IllegalStateException.class, rootCause(e));
}
+ @Test
+ public void
testBeanRouterWithCorrelationIdAddsCamelSmooksExecutionContextHeader() throws
Exception {
+ endpoint.setExpectedMessageCount(1);
+ endpoint.expectedBodiesReceived(myBean);
+ endpoint.expectedHeaderReceived("orderId", "order-1");
+
endpoint.expectedHeaderReceived(SmooksConstants.SMOOKS_EXECUTION_CONTEXT,
smooksExecutionContext);
+
+ BeanRouter beanRouter = createBeanRouter(BEAN_ID, END_POINT_URI);
+ beanRouter.setCorrelationIdName("orderId");
+ beanRouter.setCorrelationIdPattern("order-1");
+ beanRouter.visitAfter(null, smooksExecutionContext);
+
+ endpoint.assertIsSatisfied();
+ }
+
private static Throwable rootCause(Throwable throwable) {
Throwable cause = throwable;
while (cause.getCause() != null) {