2017-08-18 1 views
1

J'essaie de consommer entièrement une ressource paginée comme suit, mais mon approche consiste à déclencher une exception StackOverflowException. Tout indice abonde-t-il? Ou une approche différente?Flux d'intégration accédant à une ressource http paginée

Exemple: https://gist.github.com/daniel-frank/a88fa4553ed34c348528f51d33c3733b

+1

Je ne vois rien de suspect. Peut-être que vous pouvez partager une trace de pile sur le sujet pour déterminer le point de 'StackOverflowException'? –

+0

Bien sûr! Gist mis à jour avec le fichier journal complet. –

Répondre

1

OK. Je vois maintenant. Permettez-moi de simplifier votre code récursif pour montrer le problème:

private IntegrationFlow getPageFlow() { 
     return f -> f 
       .publishSubscribeChannel(ps -> ps 
         .subscribe(this.nextPageFlow()) 
       ); 
    } 


private IntegrationFlow nextPageFlow() { 
     return f -> f 
       .publishSubscribeChannel(ps -> ps 
         .subscribe(this.getPageFlow()) 
       ); 
} 

Ainsi, sur le plan technique que nous avons cette structure dans la mémoire:

getPageFlow 
    nextPageFlow 
     getPageFlow 
      nextPageFlow 
       getPageFlow 

et ainsi de suite.

Un autre problème ici que chaque .subscribe(this.nextPageFlow()) crée une nouvelle instance du IntegrationFlow pendant que logiquement vous n'en attendez qu'un seul.

Je comprends que vous ne pouvez pas déclarer les beans dans le IntegrationFlowAdapter impl, mais cela n'aura pas avec le StackOverflowException de toute façon.

Ce que je vois comme un problème dans votre approche est un manque de l'abstraction MessageChannel.

Vous utilisez publishSubscribeChannel partout, pendant ce temps vous pouvez simplement distinguer la logique par la définition de canal explicite dans votre flux.

Briser la récursion et de garder le code comme plus proche de votre solution possible que je ferais comme ceci:

private IntegrationFlow getPageFlow() { 
     return f -> f 
       .channel("pageServiceChannel") 
       .handle(Http 
          .outboundGateway("https://jobs.github.com/positions.json?description={description}&page={page}") 
... 

    private IntegrationFlow nextPageFlow() { 
     return f -> f 
       .filter("!payload.isEmpty()") 
       .enrichHeaders(e -> e.headerExpression("page", "headers.getOrDefault('page', 0) + 1", true)) 
       .channel("pageServiceChannel"); 
    } 

Bien sûr, vous avez encore une récursion, mais ce sera déjà au moment de l'exécution, logique.

+0

Je comprends. Les canaux sont des citoyens de première classe dans Spring Integration, même si je préfère normalement une approche plus «safe type» reliant les flux aux flux (par exemple: subFlowMapping au lieu de channelMapping dans les routeurs). Je vous remercie! –

+1

Vous pouvez toujours garder "type safe" via des méthodes qui retournent les canaux. Mais je vois ce que tu veux dire. Malheureusement, il n'y a aucune possibilité d'arrêter la récurrence de la déclaration si nous appelons simplement la méthode de la méthode et retour. –