GH-3249: Fix RemoteFileTemplate dead lock in send
Fixes: https://github.com/spring-projects/spring-integration/issues/3249 When the `CachingSessionFactory` is configured with small enough pool and it is very likely that dead lock may happen when `RemoteFileTemplate.send()` is used. The problem happens when we reach the `RemoteFileTemplate.exists()` call which is done from the internal method called from already pulled from cache `Session` * Fix `RemoteFileTemplate` to use a `session.exists()` instead on the provided into the method `Session` * Demonstrate the problem in the `SftpRemoteFileTemplateTests.testNoDeadLockOnSend()` **Cherry-pick to 5.2.x, 5.1.x & 4.3.x** Fix RemoteFileOutboundGWTests for the proper mock
This commit is contained in:
committed by
Gary Russell
parent
baac0a198b
commit
e73e08b968
@@ -386,7 +386,7 @@ public class RemoteFileTemplate<F> implements RemoteFileOperations<F>, Initializ
|
||||
public boolean get(Message<?> message, InputStreamCallback callback) {
|
||||
Assert.notNull(this.fileNameProcessor, "A 'fileNameExpression' is needed to use get");
|
||||
String remotePath = this.fileNameProcessor.processMessage(message);
|
||||
return this.get(remotePath, callback);
|
||||
return get(remotePath, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -571,7 +571,7 @@ public class RemoteFileTemplate<F> implements RemoteFileOperations<F>, Initializ
|
||||
session.append(stream, tempFilePath);
|
||||
}
|
||||
else {
|
||||
if (exists(remoteFilePath)) {
|
||||
if (session.exists(remoteFilePath)) {
|
||||
if (FileExistsMode.FAIL.equals(mode)) {
|
||||
throw new MessagingException(
|
||||
"The destination file already exists at '" + remoteFilePath + "'.");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.willReturn;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -804,14 +805,10 @@ public class RemoteFileOutboundGatewayTests {
|
||||
SessionFactory<TestLsEntry> sessionFactory = mock(SessionFactory.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Session<TestLsEntry> session = mock(Session.class);
|
||||
RemoteFileTemplate<TestLsEntry> template = new RemoteFileTemplate<TestLsEntry>(sessionFactory) {
|
||||
|
||||
@Override
|
||||
public boolean exists(String path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
willReturn(Boolean.TRUE)
|
||||
.given(session)
|
||||
.exists(anyString());
|
||||
RemoteFileTemplate<TestLsEntry> template = new RemoteFileTemplate<>(sessionFactory);
|
||||
template.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
|
||||
template.setBeanFactory(mock(BeanFactory.class));
|
||||
template.afterPropertiesSet();
|
||||
@@ -932,7 +929,7 @@ public class RemoteFileOutboundGatewayTests {
|
||||
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "mput", null);
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> gw.setRemoteDirectoryExpression(new LiteralExpression("testRemoteDirectory")))
|
||||
.withMessageContaining("The 'remoteDirectoryExpression' must be set on the externally provided");
|
||||
.withMessageContaining("The 'remoteDirectoryExpression' must be set on the externally provided");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -942,6 +939,7 @@ public class RemoteFileOutboundGatewayTests {
|
||||
Session<TestLsEntry> session = mock(Session.class);
|
||||
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(sessionFactory, "mput", "payload");
|
||||
gw.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
|
||||
gw.setBeanFactory(mock(BeanFactory.class));
|
||||
gw.afterPropertiesSet();
|
||||
when(sessionFactory.getSession()).thenReturn(session);
|
||||
final AtomicReference<String> written = new AtomicReference<>();
|
||||
|
||||
Reference in New Issue
Block a user