Federico Mariani created CAMEL-24121:
----------------------------------------
Summary: camel-smb: producer with tempPrefix/tempFileName always
fails with NullPointerException - existsFile is called before any connect
Key: CAMEL-24121
URL: https://issues.apache.org/jira/browse/CAMEL-24121
Project: Camel
Issue Type: Bug
Components: camel-smb
Affects Versions: 4.21.0
Reporter: Federico Mariani
h3. Problem
{{SmbOperations.existsFile}} (SmbOperations.java:203-205) is the only remote
operation in the class that neither calls {{connectIfNecessary()}} nor guards
the {{share}} field:
{code:java}
@Override
public boolean existsFile(String name) throws
GenericFileOperationFailedException {
return share.fileExists(name); // share is null until
connectIfNecessary()
}
{code}
When a temp file name is configured, {{GenericFileProducer.processExchange}}
calls {{preWriteCheck(exchange)}} and then {{operations.existsFile(target)}} /
{{existsFile(tempTarget)}} (GenericFileProducer.java:148,158) *before* any
store operation. FTP's {{RemoteFileProducer.preWriteCheck}} overrides the hook
to {{connectIfNecessary()}}; {{SmbProducer}} does not override it. Since
{{SmbEndpoint.isSingletonProducer()}} is {{false}}, every send gets a fresh,
unconnected {{SmbOperations}} - so any producer route using {{tempPrefix}} or
{{tempFileName}} throws NPE on *every* exchange:
{noformat}
java.lang.NullPointerException: Cannot invoke
"com.hierynomus.smbj.share.DiskShare.fileExists(String)" because "this.share"
is null
at
org.apache.camel.component.smb.SmbOperations.existsFile(SmbOperations.java:204)
at
org.apache.camel.component.file.GenericFileProducer.processExchange(GenericFileProducer.java:148)
{noformat}
h3. Failure scenario
{{from("direct:start").to("smb:host/share/dir?username=...&password=...&tempPrefix=inprogress-")}}
- fails with the NPE above on the first and every message. The two options are
unusable on camel-smb.
h3. History
{{existsFile}} has been connect-less since the CAMEL-21352 rework introduced
{{SmbOperations}}. All in-tree ITs exercise {{existsFile}} only after a
store/consume has already connected, which is why it went unnoticed - there is
no tempPrefix/tempFileName IT.
h3. Related latent gap
{{storeFileDirectly}} (checksum file writing, SmbOperations.java:528-543) has
the same missing {{connectIfNecessary()}}, and {{existsFile}}/{{deleteFile}}
also bypass the {{safeDisconnect}} transport-error handling that
{{listFiles}}/{{retrieve}}/{{rename}} apply. Worth fixing in the same pass.
h3. Suggested fix
Add {{connectIfNecessary()}} to {{existsFile}} (and {{storeFileDirectly}}),
and/or override {{preWriteCheck}} in {{SmbProducer}} the way FTP does.
h3. Reproducer
Attached failing IT (place in
{{components/camel-smb/src/test/java/org/apache/camel/component/smb/}}).
----
_This issue was researched and filed by Claude Code on behalf of [~fmariani]
(GitHub: Croway), as part of a deep code review of camel-smb. A failing JUnit
reproducer is attached; it fails deterministically on current main
(4.22.0-SNAPSHOT) against the Samba testcontainer used by the existing
camel-smb ITs._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)