2017-06-22 2 views
2

J'ai les exigences suivantes.CompletableFuture obtenir le résultat du premier avenir en attente d'autres contrats à terme en fonction de la première

  1. CreateDocument
  2. Pour le document créer de nombreuses notes de version (releaseNotesFuture)
  3. pour le document créer de nombreuses parcelles (parcelsFuture)
  4. retour objectId du document créé dans 1.

c'est mon Code actuel:

public CompletableFuture<ObjectId> createDeliveryNoteDocument(String productId, List<String> releaseNotesIds) { 
     CompletableFuture<ObjectId> deliveryNoteFuture = 
       CompletableFuture 
         .supplyAsync(() -> sequenceServiceFeignClient.getNextValueForSequenceNameNoResponseEntity(DocumentType.DELIVERYNOTE.toString())) 
         .whenComplete((result, error) -> { 
          if (error != null) 
           logger.error("Unable to get next sequence number for DELIVERYNOTE sequence", error); 
         }) 
         .thenCompose(seqNumber -> { 
          Set<ObjectAttribute> objectAttributes = new HashSet<>(); 
          objectAttributes.add(new ObjectAttribute(Constants.Document.DOCUMENT_TYPE, DocumentType.DELIVERYNOTE.toString())); 
          objectAttributes.add(new ObjectAttribute(Constants.Document.DOCUMENT_NO, seqNumber)); 
          objectAttributes.add(new ObjectAttribute(Constants.Document.PRODUCT_ID, productId)); 
          return objectCommandService.createCustomObject(new ObjectTypeTableName(Constants.ObjectTables.DOCUMENT), objectAttributes); 
         }); 
     CompletableFuture<Void> releaseNotesFuture = 
       deliveryNoteFuture 
         .thenComposeAsync(deliveryNoteId -> joinReleaseNotesWithDeliveryNote(deliveryNoteId, releaseNotesIds)); 

     CompletableFuture<Void> parcelsFuture = 
       deliveryNoteFuture 
         .thenComposeAsync(deliveryNoteId -> changeParcelsStatusForReleaseNotes(releaseNotesIds)); 

     return deliveryNoteFuture; 
    } 

Comment puis-je attendre releaseNotesFuture et parcelsFuture complétion et puis retourner deliveryNoteFuture résultat ou erreur si l'un des releaseNotesFuture ou parcelsFuture terminé exceptionnellement?

Répondre

4

au lieu de retourner deliveryNoteFuture, vous devrez avoir un CompletableFuture qui est terminée lorsque le releaseNotesFuture et parcelsFuture sont terminés. En outre, vous voulez que cet avenir compose ensuite dans le résultat de deliveryNoteFuture, puisque vous voulez que son ObjectId si la chaîne entière est réussie.

Quelque chose comme

return CompletableFuture.allOf(releaseNotesFuture, parcelsFuture).thenComposeAsync(r -> deliveryNoteFuture); 

Depuis deux releaseNotesFuture et parcelsFuture dépendent deliveryNoteFuture, des erreurs de deliveryNoteFuture se propagent à travers toutes ces chaînes.

De même, si l'une des releaseNotesFuture ou parcelsFuture échouent, la CompletableFuture returned by allOf sera complétée par la cause de cet échec et cette cause sont répercutées sur l'avenir retourné par thenComposeAsync. Sinon, le résultat de deliveryNoteFuture sera livré.


Comme Holger suggests, puisque vous avez seulement ces deux contrats à terme, vous pouvez également utiliser thenCombine

releaseNotesFuture.thenCombineAsync(parcelsFuture, (x, y) -> deliveryNoteFuture.join()); 

Ici, le join() ne bloque pas depuis deliveryNoteFuture est certainement déjà terminé. Encore une fois, si le deliveryNoteFuture avait échoué à l'origine, sa cause sera propagée dans la chaîne se terminant par le CompletableFuture retourné par thenCombineAsync.

+4

Ou 'releaseNotesFuture.thenCombine (parcelsFuture, (x, y) -> deliveryNoteFuture.join());' – Holger

+1

merci les deux ... vous deux. Finalement, j'ai utilisé la solution de Holger parce que c'est vraiment facile. – bilak