Поскольку вы отметили spring-boot
, я предполагаю, что вы его используете, и ваши услуги написаны на Spring framework. поэтому я предоставил ответ, связанный с фреймворком Spring.
прежде всего я создал интерфейс для реализации rest API как asyn c.
public interface AsyncRestCall<T> {
/** this is a hypothetical method with hypothetical params!*/
CompletableFuture<T> call(String bankAccountId);
String type();
}
, тогда вы можете иметь реализация для вашей службы такая:
Как вы видите в этой реализации, я использовал MortgageRest
, который представляет собой службу отдыха для Mortgage
.
@Service
public class MortgageService implements AsyncRestCall<MortgageInfo> {
private final MortgageRest mortgageRest;
@Autowired
public MortgageService(MortgageRest mortgageRest) {
this.mortgageRest = mortgageRest;
}
@Override
public CompletableFuture<MortgageInfo> call(String bankAccountId) {
return CompletableFuture.supplyAsync(() -> mortgageRest.service(bankAccountId));
}
@Override
public String type() {
return "mortgage";
}
}
Остаточная ипотека:
@Service
public class MortgageRest {
private RestTemplate restTemplate;
public MortgageRest(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public MortgageInfo service(String bankAccountId) {
return new MortgageInfo("123455" + bankAccountId);
}
}
для других сервисов отдыха сделайте это.
@Service
public class TransactionService implements AsyncRestCall<Transactions> {
private final TransactionRest transactionRest;
public TransactionService(TransactionRest transactionRest) {
this.transactionRest = transactionRest;
}
@Override
public CompletableFuture<Transactions> call(String bankAccountId) {
return CompletableFuture.supplyAsync(transactionRest::service);
}
@Override
public String type() {
return "transactions";
}
}
TransactionRest:
@Service
public class TransactionRest {
public Transactions service() {
return new Transactions(12);
}
}
теперь вам нужно иметь доступ ко всем реализациям AsyncRestCall
. для этого порпуса вы можете объявить класс примерно так:
@Service
public class RestCallHolder {
private final List<AsyncRestCall> asyncRestCalls;
public RestCallHolder(List<AsyncRestCall> asyncRestCalls) {
this.asyncRestCalls = asyncRestCalls;
}
public List<AsyncRestCall> getAsyncRestCalls() {
return asyncRestCalls;
}
}
AccountDetailService
(вы можете назвать то, что вам нравится) использует CompleteableFuture
для параллельного вызова сервисов отдыха.
в этом serv ie каждый bankAccountId
rest вызовы будут сохраняться в Map<String, Map<String, Object>> result = new HashMap<>();
, что внешний ключ карты будет хранить значение bankAccountId
как ключ, а его значение - это вызовы rest services, которые они сохранят на карте (внутренняя карта). ключ - это тип, а значение - это ответ на вызов. в конце путем перебора accountDetails обновит свои свойства.
@Service
public class AccountDetailService {
private final RestCallHolder restCallHolder;
public AccountDetailService(RestCallHolder restCallHolder) {
this.restCallHolder = restCallHolder;
}
public List<AccountDetail> update(List<AccountDetail> accountDetails) {
Map<String, Map<String, Object>> result = new HashMap<>();
List<AccountDetail> finalAccountDetails = new ArrayList<>();
accountDetails.forEach(accountDetail -> {
List<CompletableFuture> futures = restCallHolder.getAsyncRestCalls()
.stream()
.map(rest -> rest.call(accountDetail.getBankAccountId()))
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
.thenAccept(aVoid -> {
Map<String, Object> res = restCallHolder.getAsyncRestCalls()
.stream()
.map(rest -> new AbstractMap.SimpleEntry<>(rest.type(),
rest.call(accountDetail.getBankAccountId()).join()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
result.put(accountDetail.getBankAccountId(), res);
}
).handle((aVoid, throwable) -> {
return null; // handle the exception here
}).join();
}
);
accountDetails.forEach(accountDetail -> finalAccountDetails.add(AccountDetail.builder()
.bankAccountId(accountDetail.getBankAccountId())
.mortgageAccountId(((MortgageInfo) result.get(accountDetail.getBankAccountId()).get("mortgage")).getMortgageAccountId())
.noOfTrans(((Transactions) result.get(accountDetail.getBankAccountId()).get("transactions")).getNoOfTrans())
.build()));
return finalAccountDetails;
}
}