This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch ftp in repository https://gitbox.apache.org/repos/asf/camel.git
commit 279a023994f01c31833da2da64e8c69204cb14f6 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Jun 19 14:34:19 2025 +0200 CAMEL-22177: camel-ftp/camel-smb/camel-azure-files: Keep attempt to create starting dir if failed in doStart so we can recover. --- .../camel/component/file/azure/FilesConsumer.java | 2 +- .../component/file/remote/RemoteFileConsumer.java | 32 ++++++++++++++++++++-- .../apache/camel/component/smb/SmbConsumer.java | 32 ++++++++++++++++++++-- .../ROOT/pages/camel-4x-upgrade-guide-4_13.adoc | 7 ++++- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesConsumer.java b/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesConsumer.java index 80ac733f457..d3936771729 100644 --- a/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesConsumer.java +++ b/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesConsumer.java @@ -72,7 +72,7 @@ public class FilesConsumer extends RemoteFileConsumer<ShareFileItem> { LOG.debug("Auto creating directory: {}", endpointPath); try { connectIfNecessary(); - operations.buildDirectory(endpointPath, true); + getOperations().buildDirectory(endpointPath, true); } catch (GenericFileOperationFailedException e) { // log a WARN as we want to start the consumer. LOG.warn("Error auto creating directory: {} due to {}. This exception is ignored.", endpointPath, diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java index 0031178e20f..967e00c0e22 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/RemoteFileConsumer.java @@ -40,6 +40,8 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { protected transient boolean loggedIn; protected transient boolean loggedInWarning; + protected transient boolean autoCreatedDone; + protected transient boolean autoCreateWarning; protected RemoteFileConsumer(RemoteFileEndpoint<T> endpoint, Processor processor, RemoteFileOperations<T> operations, GenericFileProcessStrategy processStrategy) { @@ -72,17 +74,35 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { if (LOG.isTraceEnabled()) { LOG.trace("prePollCheck on {}", getEndpoint().getConfiguration().remoteServerInformation()); } + Exception cause; try { connectIfNecessary(); + loggedIn = true; + if (!autoCreatedDone) { + autoCreateIfNecessary(); + autoCreatedDone = true; + } } catch (Exception e) { + cause = e; + String msg = "Cannot connect/login to: " + remoteServer(); + if (loggedIn && !autoCreatedDone) { + msg = "Cannot auto-create starting directory at: " + remoteServer(); + } + LOG.debug(msg, cause); loggedIn = false; - - // login failed should we thrown exception if (getEndpoint().getConfiguration().isThrowExceptionOnConnectFailed()) { throw e; } } + if (loggedIn && !autoCreatedDone) { + String message = "Cannot auto-create starting directory at: " + remoteServer() + ". Will skip this poll."; + if (!autoCreateWarning) { + LOG.warn(message); + autoCreateWarning = true; + } + return false; + } if (!loggedIn) { String message = "Cannot connect/login to: " + remoteServer() + ". Will skip this poll."; if (!loggedInWarning) { @@ -233,6 +253,14 @@ public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { } } + protected void autoCreateIfNecessary() throws GenericFileOperationFailedException { + if (endpoint.isAutoCreate() && hasStartingDirectory()) { + String dir = endpoint.getConfiguration().getDirectory(); + LOG.debug("Auto creating directory: {}", dir); + getOperations().buildDirectory(dir, true); + } + } + /** * Returns human-readable server information for logging purpose */ diff --git a/components/camel-smb/src/main/java/org/apache/camel/component/smb/SmbConsumer.java b/components/camel-smb/src/main/java/org/apache/camel/component/smb/SmbConsumer.java index 8a162801b25..6cb966ac250 100644 --- a/components/camel-smb/src/main/java/org/apache/camel/component/smb/SmbConsumer.java +++ b/components/camel-smb/src/main/java/org/apache/camel/component/smb/SmbConsumer.java @@ -52,6 +52,8 @@ public class SmbConsumer extends GenericFileConsumer<FileIdBothDirectoryInformat private final String endpointPath; protected transient boolean loggedIn; protected transient boolean loggedInWarning; + protected transient boolean autoCreatedDone; + protected transient boolean autoCreateWarning; public SmbConsumer(SmbEndpoint endpoint, Processor processor, GenericFileOperations<FileIdBothDirectoryInformation> fileOperations, @@ -207,18 +209,34 @@ public class SmbConsumer extends GenericFileConsumer<FileIdBothDirectoryInformat if (LOG.isTraceEnabled()) { LOG.trace("prePollCheck on {}", getEndpoint()); } + Exception cause; try { getOperations().connectIfNecessary(); loggedIn = true; + if (!autoCreatedDone) { + autoCreateIfNecessary(); + autoCreatedDone = true; + } } catch (Exception e) { + cause = e; + String msg = "Cannot connect/login to: " + remoteServer(); + if (loggedIn && !autoCreatedDone) { + msg = "Cannot auto-create starting directory at: " + remoteServer(); + } + LOG.debug(msg, cause); loggedIn = false; - - // login failed should we thrown exception if (configuration.isThrowExceptionOnConnectFailed()) { throw e; } } - + if (loggedIn && !autoCreatedDone) { + String message = "Cannot auto-create starting directory at: " + remoteServer() + ". Will skip this poll."; + if (!autoCreateWarning) { + LOG.warn(message); + autoCreateWarning = true; + } + return false; + } if (!loggedIn) { String message = "Cannot connect/login to: " + remoteServer() + ". Will skip this poll."; if (!loggedInWarning) { @@ -237,6 +255,14 @@ public class SmbConsumer extends GenericFileConsumer<FileIdBothDirectoryInformat return true; } + protected void autoCreateIfNecessary() throws GenericFileOperationFailedException { + if (endpoint.isAutoCreate() && hasStartingDirectory()) { + String dir = endpoint.getConfiguration().getDirectory(); + LOG.debug("Auto creating directory: {}", dir); + operations.buildDirectory(dir, true); + } + } + /** * Returns human-readable server information for logging purpose */ diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_13.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_13.adoc index 58c91378345..0d753ee6610 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_13.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_13.adoc @@ -11,7 +11,7 @@ from both 4.0 to 4.1 and 4.1 to 4.2. Added a 2nd `lookup` method to `org.apache.camel.spi.TypeConverterRegistry` and changed the `addConverter` to no longer have an empty default noop implementation in the interface. -=== camel-file / camel-ftp / camel-smb +=== camel-file / camel-ftp / camel-smb / camel-azure-files When using `poll` or `pollEnrich` with the file based components, then the `eagerLimitMaxMessagesPerPoll` option has changed default from `false` to `true`. Only use-cases where you need to sort the files first, @@ -20,6 +20,11 @@ and then `poll` or `pollEnrich` will then pick the top file after the sorting. This improves performance for use-cases without need for sorting first. +The consumers (`camel-ftp`, `camel-smb`, and `camel-azure-files`) will now in case of failure to create starting directory, +on startup, keep attempting to create the directory on polling, until its successfully created. +Previously in case of error creating the starting directory then this could cause the consumer to not be able to recover, +and you would have to restart the route to attempt again. + === camel-http Renamed class `org.apache.camel.component.http.BasicAuthenticationHttpClientConfigurer` to `org.apache.camel.component.http.DefaultAuthenticationHttpClientConfigurer`.