2017-03-27 1 views
0

J'ai écrit un morceau de code qui utilise la passerelle sortante Spring SFTP et effectue une opération GET. La configuration complète est en Java (pas de XML). J'ai créé une fabrique de sessions de mise en cache qui permet un maximum de 10 sessions. En raison de quoi, après plusieurs requêtes GET quand il dépasse 10, la requête GET commence à échouer.Spring SFTP Outbound Gateway: Comment fermer la session après GET dans Java Config?

J'ai lu les documents et il a été écrit pour fermer la session après l'opération, mais je suis incapable de comprendre comment fermer cette session dans la configuration JAVA?

@org.springframework.integration.annotation.MessagingGateway 
public interface FileOperationGateway { 
    @Gateway(requestChannel = "sftpChannelDownload") 
    InputStream downloadFromSftp(Message<Boolean> message); 

} 



@Bean 
public SessionFactory<LsEntry> sftpSessionFactory() { 
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true); 
    factory.setHost(SFTP_HOST); 
    factory.setPort(SFTP_PORT); 
    factory.setUser(SFTP_USERNAME); 
    factory.setPassword(SFTP_PASSWORD); 
    factory.setAllowUnknownKeys(true); 
    return new CachingSessionFactory<LsEntry>(factory); 
} 

/** 
* Bean for Caching the session 
* 
*/ 

@Bean 
@Autowired 
public CachingSessionFactory<LsEntry> cachingSessionFactory(SessionFactory<LsEntry> sftpSessionFactory) { 
    CachingSessionFactory<LsEntry> cachingSessionFactory = new CachingSessionFactory<>(sftpSessionFactory, 10); 
    cachingSessionFactory.setSessionWaitTimeout(SFTP_SESSION_TIMEOUT); 
    return cachingSessionFactory; 
} 

/** 
* Bean for Remote File Template 
* 
* @return 
* @throws Exception 
*/ 

@Bean 
@Autowired 
public RemoteFileTemplate<LsEntry> remoteFileTemplateDesigner(CachingSessionFactory<LsEntry> csf) throws Exception { 
    ExpressionParser expressionParser = new SpelExpressionParser(); 
    Expression expression = expressionParser.parseExpression("'" + SFTP_LOCATION + "'"); 
    SftpRemoteFileTemplate rft = new SftpRemoteFileTemplate(csf); 
    rft.setRemoteDirectoryExpression(expression); 
    rft.setRemoteFileSeparator("/"); 
    rft.setFileNameGenerator((msg) -> { 
     Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 
     Instant instant = timestamp.toInstant(); 
     String fileNameFromHeader = msg.getHeaders().get(FileOperationConstants.FILE_HEADER_KEY).toString(); 
     String newFileName; 
     if (fileNameFromHeader.lastIndexOf("/") != -1) { 
      newFileName = fileNameFromHeader.substring(fileNameFromHeader.lastIndexOf("/")); 
     } else if (fileNameFromHeader.lastIndexOf("\\") != -1) { 
      newFileName = fileNameFromHeader.substring(fileNameFromHeader.lastIndexOf("\\")); 
     } else 
      newFileName = fileNameFromHeader; 

     String fileNameOnly = newFileName.substring(0, newFileName.lastIndexOf(".")); 
     String fileType = newFileName.substring(newFileName.lastIndexOf(".") + 1); 
     return (fileNameOnly + "__" + instant.toString() + "." + fileType); 
    }); 
    rft.afterPropertiesSet(); 
    return rft; 
} 

@Bean 
@Autowired 
@ServiceActivator(inputChannel = "sftpChannelDownload") 
public SftpOutboundGatewaySpec downloadHandler(RemoteFileTemplate<LsEntry> rft) { 
    SftpOutboundGatewaySpec sogs = Sftp.outboundGateway(rft, FileOperationConstants.FILE_DOWNLOAD_COMMAND, 
      FileOperationConstants.FILE_DOWNLOAD_EXPRESSION); 
    sogs.options(Option.STREAM); 
    return sogs; 
} 

****** MISE À JOUR: ******

J'ai créé une nouvelle classe avec @messageEndpoint et placé le code de la session refermable en elle. J'ai ensuite appelé ce gestionnaire de ma classe de service (où je consommais le flux) Cela a fonctionné:

@MessageEndpoint 
public class FileOperationCloseSessionMessageHandler { 

    @ServiceActivator(inputChannel = "sftpCloseSession") 
    public void closeSession(Message<Boolean> msg) throws IOException { 

     Closeable closeable = new IntegrationMessageHeaderAccessor(msg).getCloseableResource(); 
     if (closeable != null) { 
      closeable.close(); 
     } 
    } 
} 

Placée cette ligne dans la classe annotée @MessagingGateway

@Gateway(requestChannel = "sftpCloseSession") 
void closeSession(Message<InputStream> msg); 

Et puis appelé la méthode de la passerelle du service classe:

Message<InputStream> msg = msgGateway.downloadFromSftp(message); 
    InputStream is = msg.getPayload(); 
    msgGateway.closeSession(msg); 

Répondre

0

sogs.options (Option.STREAM); Lorsque vous diffusez le fichier, vous êtes responsable de la fermeture de la session après la fin du streaming. Ceci est expliqué dans the documentation. Lorsque vous consommez des fichiers distants en tant que flux, l'utilisateur est responsable de la fermeture de la session une fois le flux consommé. Pour plus de commodité, la session est fourni dans l'en-tête de IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE, une méthode pratique est fourni sur le IntegrationMessageHeaderAccessor:

Closeable closeable = new IntegrationMessageHeaderAccessor(message).getCloseableResource(); 
if (closeable != null) { 
    closeable.close(); 
} 

composants cadres tels que le séparateur de fichiers et transformateur Stream fermera automatiquement la session après les données sont transférées.

+0

Salut Gary, Merci pour la réponse. Je savais déjà que ce morceau de code "fermable" peut être utilisé pour fermer la session mais le problème est où et comment l'utiliser? devrais-je créer une nouvelle méthode @serviceActivator et placer ceci dans cela? Pouvez-vous s'il vous plaît montrer avec le code? –

+0

J'ai trouvé la solution et l'ai mise à jour. Merci. –