2017-06-19 28 views
0

之前在我MainVerticle我設置路由器異步性在Vertx,它被設置

router.get("/persons").handler(ctx -> apiService.getPersons(ctx, client)); 

我要調用兩次相同的主機列表返回空,首先我需要的人ID的列表,然後調用同一個主機的另一種方法來獲取人員詳細信息。 。所以,在這段代碼中,我正在另一個接聽電話。由於異步性,personList是空的,因爲Vertx不等待第二個呼叫的回覆,第二個呼叫的回覆稍後出現,但是當然personList是空的。在我的測試案例中,迭代器有兩個元素。我應該如何實現它以確保列表將被正確返回?

 public void getPersons(RoutingContext routingContext, WebClient client){ 
    logger.info("getpersons"); 
    routingContext.response().headers().add("content-type", "application/json"); 
    String wshost= ConfigUtils.getStringConfig(vertx,"personws.url"); 
    String url = wshost+"/persons"; 
    client.getAbs(url).send(response -> { 
     try { 
      if (response.succeeded() && response.result().statusCode()==200) { 
       List<Person> personList = new ArrayList<Person>(); 
       logger.info("Server content " + response.result().bodyAsString()); 

       Iterator<Object> iterator = response.result().bodyAsJsonArray().iterator(); 
       while(iterator.hasNext()){ 
        Object obj = iterator.next(); 
        JsonObject jsonPerson = (JsonObject) obj ; 
        logger.debug("personId: {}", jsonPerson.getString("id")); 
        Person person = new Person(); 
        person.setId(jsonPerson.getString("id")); 

        String url2 = wshost+"/persons/"+jsonPerson.getString("id"); 
        logger.info("Calling ws to get person details for : {}", jsonPerson.getString("id"), url2); 
        client.getAbs(url2).send(response2 -> { 
         if (response2.succeeded() && response2.result().statusCode()==200) { 

          JsonObject jsonDetails = response2.result().bodyAsJsonObject(); 
          person.setDetail(jsonDetails); 
          personList.add(person); 
          logger.info("person is {} ", person); 
          logger.info("iterator.hasNext():{}", iterator.hasNext()); 


         } 
         else{ 
          routingContext.response().setStatusCode(500); 
          routingContext.response().end(buildError("Failed to get json ", 600).encode()); 
         } 

        }); 

       }; 
       logger.info("personList: {} ", personList); 
       logger.info("personList size {} ", personList.size()); 
       routingContext.response().setStatusCode(200).end(new JsonArray(personList).toString()); 
      } else { 
       logger.error("Cannot get persons"); 
       routingContext.response().setStatusCode(500); 
       routingContext.response().end(buildError("Failed to get persons", 100).encode()); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      routingContext.response().setStatusCode(500); 
      routingContext.response().end(buildError("Exception in API- Failed to get get persons for fleet "+routingContext.request().headers().get("fleet"), 300).encode()); 
     } 

    }); 

} 

回答

0

首先,你不要只打電話給你的主機兩次。您在初始請求中按每個人數調用n + 1次。

最簡單的方式來實現你需要的是算你希望得到的人數:

   int expected = response.result().bodyAsJsonArray().size(); 

       Iterator<Object> iterator = response.result().bodyAsJsonArray().iterator(); 
       while(iterator.hasNext()){ 
        Object obj = iterator.next(); 
        JsonObject jsonPerson = (JsonObject) obj ; 
        logger.debug("personId: {}", jsonPerson.getString("id")); 
        Person person = new Person(); 
        person.setId(jsonPerson.getString("id")); 

        String url2 = wshost+"/persons/"+jsonPerson.getString("id"); 
        logger.info("Calling ws to get person details for : {}", jsonPerson.getString("id"), url2); 
        client.getAbs(url2).send(response2 -> { 
         if (response2.succeeded() && response2.result().statusCode()==200) { 

          JsonObject jsonDetails = response2.result().bodyAsJsonObject(); 
          person.setDetail(jsonDetails); 
          personList.add(person); 
          logger.info("person is {} ", person); 
          logger.info("iterator.hasNext():{}", iterator.hasNext()); 

          // That's the last one 
          if (personList.size() == expected) { 
           // Only now complete the request 
           routingContext.response().setStatusCode(200).end(new JsonArray(personList).toString()); 
          } 
         } 
         else{ 
          routingContext.response().setStatusCode(500); 
          routingContext.response().end(buildError("Failed to get json ", 600).encode()); 
         } 

        }); 

       }; 
       logger.info("personList: {} ", personList); 
       logger.info("personList size {} ", personList.size()); 
       // Moved inside callback 

其他的方式是使用CompositeFuture: http://vertx.io/docs/vertx-core/groovy/#_concurrent_composition

+0

你是對的,再加上我意識到我需要添加一個處理程序來異步管理結果 – Grandmaster

相關問題