title: Using DelegatingSessionFactory with RemoteFileTemplate.execute(SessionCallback)
body: <p>I'm trying to declare multiple SFTP sessions, wrap them in a DelegatingSessionFactory, then later use SftpRemoteFileTemplate.execute(...) during a cron job.</p>
  <p>On the execute part of things, the code is very simple, it is already used for a single session, but I want to expand it to multiple possible sessions.</p>
  <p>Below I extended my single session code. I just copied the methods for reference. At the end I'll show how I think the new methods should look.</p>
  <pre><code>public class XSession extends SftpSession {
  
      @Scheduled(cron = &quot;${sftp.scan.x.schedule}&quot;)
      void scan() {
          List&lt;FileHistoryEntity&gt; fileList = template.execute(this::processFiles);
          ...
      }
      
      private List&lt;FileHistoryEntity&gt; processFiles(Session&lt;ChannelSftp.LsEntry&gt; session) {
          List.of(session.list(this.remoteDir)).forEach(file -&gt; doWhatever());
          ...
      }
  }
  </code></pre>
  <p>But now I have multiple sessions. So I declare the following class:</p>
  <pre><code>@Slf4j
  @Configuration
  @RequiredArgsConstructor
  public class DelegateSftpSessionHandler {
  
      private final SessionFactory&lt;ChannelSftp.LsEntry&gt; session1;
      private final SessionFactory&lt;ChannelSftp.LsEntry&gt; session2;
      private final SessionFactory&lt;ChannelSftp.LsEntry&gt; session3;
      private final SessionFactory&lt;ChannelSftp.LsEntry&gt; session4;
      private final SessionFactory&lt;ChannelSftp.LsEntry&gt; session5;
      
      @RequiredArgsConstructor
      public enum DelegateSessionConfig {
          SESSION_1(&quot;IN_REALITY_A_RELEVANT_NAME_1&quot;);
          SESSION_2(&quot;IN_REALITY_A_RELEVANT_NAME_2&quot;);
          SESSION_3(&quot;IN_REALITY_A_RELEVANT_NAME_3&quot;);
          SESSION_4(&quot;IN_REALITY_A_RELEVANT_NAME_4&quot;);
          SESSION_5(&quot;IN_REALITY_A_RELEVANT_NAME_5&quot;);
  
          public final String threadKey;
      }
  
      @Bean
      @Primary
      public DelegatingSessionFactory&lt;ChannelSftp.LsEntry&gt; delegatingSessionFactory() {
          Map&lt;Object, SessionFactory&lt;ChannelSftp.LsEntry&gt;&gt; sessionMap = new HashMap&lt;&gt;();
          sessionMap.put(DelegateSessionConfig.SESSION_1.threadKey, session1);
          sessionMap.put(DelegateSessionConfig.SESSION_2.threadKey, session2);
          sessionMap.put(DelegateSessionConfig.SESSION_3.threadKey, session3);
          sessionMap.put(DelegateSessionConfig.SESSION_4.threadKey, session4);
          sessionMap.put(DelegateSessionConfig.SESSION_5.threadKey, session5);
  
          DefaultSessionFactoryLocator&lt;ChannelSftp.LsEntry&gt; sessionLocator = new DefaultSessionFactoryLocator&lt;&gt;(sessionMap);
          return new DelegatingSessionFactory&lt;&gt;(sessionLocator);
      }
  
      @Bean
      SftpRemoteFileTemplate ftpRemoteFileTemplate(DelegatingSessionFactory&lt;ChannelSftp.LsEntry&gt; dsf) {
          return new SftpRemoteFileTemplate(dsf);
      }
  }
  </code></pre>
  <p>Ting is, I have no idea how any of this works, and the spring sftp / fpt documentation is by no means clear. The code is virtually undocumented. And I'm just guessing. I think that I have to do the following:</p>
  <pre><code>public class XSession extends SftpSession {
  
      @Autowire
      DelegatingSessionFactory&lt;ChannelSftp.LsEntry&gt; delegatingSessionFactory;
      
      @Autowired
      SftpRemoteFileTemplate template;
  
      @Scheduled(cron = &quot;${sftp.scan.x.schedule}&quot;) // x == SESSION_1
      @Async // for thread key
      void scan() {
          delegatingSessionFactory.setThreadKey(DelegateSessionConfig.SESSION_1.threadKey);
          
          // because thread key changes the session globally? So I don't need specify
          // which session this template is working with???
          List&lt;FileHistoryEntity&gt; fileList = template.execute(this::processFiles);
         
          ...
         
          delegatingSessionFactory.clearThreadKey();
      }
      
      private List&lt;FileHistoryEntity&gt; processFiles(Session&lt;ChannelSftp.LsEntry&gt; session) {
          List.of(session.list(this.remoteDir)).forEach(file -&gt; doWhatever());
          ...
      }
  }
  </code></pre>
  <p>I'm basing what I'm saying on the following link, <a href="https://github.com/spring-projects/spring-integration/blob/39c3acb042c26f0141dd7c1e0d344acb2dbc5f62/spring-integration-file/src/test/java/org/springframework/integration/file/remote/session/DelegatingSessionFactoryTests.java#L77" rel="nofollow noreferrer">github spring integration test</a></p>
  <p>Honestly, I hardly understand what is happening. But it seems like setting the thread key, changes the session globally.</p>
  <p>My only other idea is to just ... create the RemoteFileTemplate on demand</p>
  <pre><code>public static SftpRemoteFileTemplate getTemplateFor(DelegatingSessionFactory&lt;ChannelSftp.LsEntry&gt; dsf, DelegateSessionConfig session) {
      return new SftpRemoteFileTemplate(dsf.getFactoryLocator().getSessionFactory(session.threadKey));
  }
  </code></pre>