Search code examples
javaspringreactor

Why my CompletableFuture never return the response i need and the api call is pending?


i have this method, who calls two APIs with POST to some url, from first response i get almost all values of my AccountBalanceResponse object and then i need to use the response of the first API to call a second API both calls return Mono objects, then when i use "mapFuture.get()" to fill the last value of my response object but the API call just dont do nothing... in log i see " o.s.w.r.f.client.ExchangeFunctions : [20852e1] HTTP POST https://apiURLICall" but the program just stay like that without given any result. Any clue? and thanks.

private Mono<AccountBalanceResponse> getDebts(UserInfo userInfo, String msisdn, String 
       codService, String documentType,
        String documentNumber) {
    AccountBalanceResponse accountBalance = new AccountBalanceResponse();
    HashMap<String, Object> listPositiveAmount = new LinkedHashMap<>();
    LOGGER.info("UserInfo: {}", userInfo);
    LOGGER.info("msisdn: {}", msisdn);
    LOGGER.info("codService: {}", codService);
    LOGGER.info("documentType: {}", documentType);
    LOGGER.info("documentNumber: {}", documentNumber);

        String accountCode = userInfo.getAccountCode();
        if (StringUtils.equals(accountCode, null)) {
            accountBalance.setErrorCode(userInfo.getErrorCode());
            accountBalance.setErrorDescription(userInfo.getErrorDescription());
            accountBalance.setStatusResponse(500);
            return Mono.just(accountBalance);
    }
        LOGGER.info("Account code: {}", accountCode);

        Mono<JsonNode> objectNode = accountBalanceRestClient.getAccountBalance(accountCode, documentNumber);
        return objectNode.map(jsonNodeResponse->{
            AccountBalanceResponse accountBalanceFuture = new AccountBalanceResponse();
            LOGGER.info("<Response Account Balance>: {}", objectNode);
            Double amountRA;
            String unitsRA;

            Integer amountPA = 0;
            String unitsPA = null;

            Mono<String> webViewPagos = null;

            JsonNode remainedAmount = jsonNodeResponse.get(0).get("remainedAmount");
            JsonNode positiveAmount = jsonNodeResponse.get(0).get("positiveAmount");

            String issueDate = StringUtils
                    .substring(jsonNodeResponse.get(0).get("validFor").get("startDateTime").asText(), 0,
                            10);
            String issueDateParsed = StringUtils.replaceEach(issueDate, new String[] { "-", "-" },
                    new String[] { "", "" });
            LOGGER.info("Issue Date: {}", issueDate);
            LOGGER.info("Issue Date Parsed: {}", issueDateParsed);
            String dueDate = calculateBillDatesUtil.calculateDueDate(issueDateParsed, "C");
            Integer statusNew = Utils.compareDateWithToday(dueDate, DATE_FORMAT);
            String statusDebt = DeudaUtil.getEstadoDeuda(statusNew.intValue());
            String codeStatusDebt = DeudaUtil.getCodigoEstadoDeuda(statusNew.intValue());

            amountRA = remainedAmount.get(AMOUNT).asDouble();
            unitsRA = remainedAmount.get(UNITS).asText();
            int receiptsTotal = 1;
            int receiptsToPay = 0;
            if (amountRA <= Double.valueOf(0.0)) {
                statusDebt = "Sin deuda";
                codeStatusDebt = "S";
            } else {
                webViewPagos = webViewPagosService.getWebViewPagosProd(msisdn, codService, documentType,
                        documentNumber);
                receiptsToPay++;
            }
            if (positiveAmount != null && positiveAmount.has(AMOUNT)) {
                amountPA = positiveAmount.get(AMOUNT).asInt();
                unitsPA = positiveAmount.get(UNITS).asText();
            }

            ObjectMapper mapper = new ObjectMapper();

            listPositiveAmount.put(AMOUNT, amountPA);
            listPositiveAmount.put(UNITS, unitsPA == null ? unitsRA : unitsPA);
            accountBalanceFuture.setSumTaxTotal(String.format("%.2f", amountRA));
            accountBalanceFuture.setInvoiceCurrency(unitsRA);
            accountBalanceFuture.setPositiveAmount(listPositiveAmount);
            accountBalanceFuture.setInvoiceDate(dueDate == null ? "null" : dueDate);
            accountBalanceFuture.setCodeStatusDebt(codeStatusDebt);
            accountBalanceFuture.setStatusDebt(statusDebt);
            accountBalanceFuture.setStatusResponse(200);
            accountBalanceFuture.setInvoiceList(mapper.createArrayNode());
            accountBalanceFuture.setReceiptsTotal(receiptsTotal);
            accountBalanceFuture.setReceiptsToPay(receiptsToPay);
            accountBalanceFuture.setCodPayment(msisdn);
            CompletableFuture<AccountBalanceResponse> mapFuture = webViewPagos.toFuture()
                .thenApplyAsync(urlResponse -> {
                    AccountBalanceResponse accountBFuture = new AccountBalanceResponse();
                    accountBFuture.setWebViewPagosURL(urlResponse);
                    return accountBFuture;
                });
            try {
            accountBalanceFuture.setWebViewPagosURL(mapFuture.get().getWebViewPagosURL());
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error(e.toString());
            Thread.currentThread().interrupt();
        }

        return accountBalanceFuture;
        });
      }

Solution

  • I have to refactor all the method i do it this way to work properly:

        public Mono<MTDebtsResponse> data(List<OpenDebtsCall> products) {
        
        
        MTDebtsResponse mtDebtsResponse = new MTDebtsResponse();
        AccountBalanceResponse responseDebtMovil = new AccountBalanceResponse();
        OpenDebtsCustomizedResponse responseDebtHogar = new OpenDebtsCustomizedResponse();
        List<String> listInvoiceTotal = new ArrayList<>();
        List<Integer> listStatusR = new ArrayList<>();
        
        GeneralSettingsBean beanGS = generalSettingsRepository.findByGsKey(IS_SUM_TAX_PRODUCTS_MT);
        String flagMT = beanGS.getGsValue();
        mtDebtsResponse.setDebtConsolidatorMode(flagMT);
        
    
        MTdebt mtDebt = new MTdebt();
        mtDebt.mtDebtsResponseg = new MTDebtsResponse();
        mtDebt.responseDebtHogarg = new OpenDebtsCustomizedResponse();
        mtDebt.responseDebtMovilg = new AccountBalanceResponse();
        mtDebt.listInvoiceTotalg =  new ArrayList<>();
        mtDebt.listStatusRg = new ArrayList<>();
        
        DebtData debData = new DebtData();
        debData.amountRADebtMovil = 0.0;
        debData.sumTaxTotal = 0.0;
        debData.receiptsToPay = 0;
        debData.receiptsTotal = 0;
        debData.traceIdDebt = null;
        debData.invoiceListNew = this.mapper.createArrayNode();
        
        Map<String, OpenDebtsOnlyResponse> mapOpenDebtsRest = new HashMap<>();
        Map<String, String> codMap = new HashMap<>();
        /*
         * switch true 1: consulta deuda MT: hogar + movil switch false 0: consulta solo
         * hogar
         */
        QATokenCloudBean qaTokenCloudBean = qaTokenCloudRepository.findTopByCodeToken(CLOUD);
        String accessToken = qaTokenCloudBean.getAccessToken();
    
        StringBuilder bearer = new StringBuilder();
        bearer.append("Bearer ");
        bearer.append(accessToken);
        
        return Flux.fromIterable(products).flatMap(product -> {
            String codPayment = product.getCodPayment();
            String codService = product.getCodService();
            String originalCodPayment = product.getCodPayment();
    
            if (StringUtils.equals(flagMT, FLAG_PRODUCTS_MT_VALUE_FALSE) && !StringUtils.equals(codService, "T")) {
                return Flux.empty();
            } else if (StringUtils.equals(codService, "T") && StringUtils.startsWith(codPayment, "1")) {
                codPayment = StringUtils.substring(codPayment, 1);
            }
            codMap.put(Constants.CODSERVICE, codService);
            codMap.put(Constants.CODPAYMENT, codPayment);
            codMap.put(Constants.ORIGINALCODPAYMENT, originalCodPayment);
            return openDebtsRestClient.getOpenDebts(codPayment, codService, bearer,
                    product.getDocumentNumber()).flatMapMany(openDebtsResponse->{
                        addMapBrainyBill(openDebtsResponse, originalCodPayment, codService, mapOpenDebtsRest);
    
                        ObjectNode data = openDebtsResponse.getOpenDebts();
                        debData.traceIdDebt = String.valueOf(openDebtsResponse.getTraceId());
                        Integer statusR = data.get(STATUS).asInt();
                        listStatusR.add(statusR);
                        mtDebt.listStatusRg = listStatusR;
                        JsonNode response = data.get(RESPONSE);
    
                        if (StringUtils.equals(codService, "T")) {
                            responseDebtHogar.setStatusResponse(statusR);
                            mtDebt.responseDebtHogarg = responseDebtHogar;
                        } else if (StringUtils.equals(codService, "C")) {
                            responseDebtMovil.setStatusResponse(statusR);
                            mtDebt.responseDebtMovilg = responseDebtMovil;
                        }
    
                        if (statusR != 200) {
                            statusR = statusR == 432 ? 200 : statusR;
                            if (StringUtils.equals(codService, "T")) {
                                responseDebtHogar.setStatusResponse(statusR);
                                responseDebtHogar.setErrorDescription(response.toString());
                                mtDebt.responseDebtHogarg = responseDebtHogar;
                            } else if (StringUtils.equals(codService, "C")) {
                                responseDebtMovil.setStatusResponse(statusR);
                                responseDebtMovil.setErrorDescription(response.toString());
                                mtDebt.responseDebtMovilg = responseDebtMovil;
                            }
    
                            LOGGER.info("codPayment: {}", codMap.get(Constants.CODPAYMENT));
                            LOGGER.info("codService: {}", codMap.get(Constants.CODSERVICE));
                            LOGGER.info("originalCodPayment: {}", codMap.get(Constants.ORIGINALCODPAYMENT));
    
                            return Flux.just(mtDebt);
                        }
                        LOGGER.info("Response OpenDebts: {}", response);
    
                        String cityCode = response.get(CITYCODE).asText();
                        ArrayNode invoiceListArray = (ArrayNode) response.get("invoiceList");
    
                        if (invoiceListArray == null || invoiceListArray.isEmpty())
                            return Flux.just(mtDebt);
    
                        debData.receiptsTotal += invoiceListArray.size();
                        List<JsonNode> listTaxTotal = invoiceListArray.findValues(TAX_TOTAL);
                        List<JsonNode> listInvoiceDate = invoiceListArray.findValues(INVOICE_DATE);
                        List<JsonNode> listInvoiceCurrency = invoiceListArray.findValues(INVOICE_CURRENCY);
                        List<JsonNode> listInvoiceNumber = invoiceListArray.findValues(INVOICE_NUMBER);
                        LOGGER.info("listTaxTotal: {}", listTaxTotal);
                        // suma de todos los recibos
                        debData.sumTaxTotal = listTaxTotal.stream().map(l -> (l.asDouble()) / 100).reduce(debData.sumTaxTotal,
                                Double::sum);
    
                        Map<String, CalculateBillDatesBean> dueDatesBeans = calculateBillDatesUtil.retrieveDueDatesMap(
                                listInvoiceDate.stream().distinct().map(JsonNode::asText).collect(Collectors.toList()), codService);
    
                        listInvoiceDate.stream().distinct().map(JsonNode::asText).map(string -> {
                            if (StringUtils.equals(codService, "T")) {
                                string = calculateBillDatesUtil.calculateDueDate(string, codService, dueDatesBeans);
                            }
                            return string;
                        }).forEachOrdered(listInvoiceTotal::add);
    
                        mtDebtsResponse.setInvoiceCurrency(listInvoiceCurrency.get(0).asText());
                        mtDebtsResponse.setInvoiceNumber(listInvoiceNumber.get(0).asText());
                        String originalInvoiceDate = listInvoiceDate.get(0).asText();
                        mtDebtsResponse.setOriginalInvoiceDate(originalInvoiceDate == null ? "" : originalInvoiceDate);
                        mtDebtsResponse.setCodService(codService);
    
                        LOGGER.info("Sum Tax Total: {}", debData.sumTaxTotal);
                        LOGGER.info("Iniciando recorrido de invoiceList");
    
                        // for que inserta todos los recibos sean moviles o fijo
                         debData.invoiceListNew = elementsToArray(invoiceListArray, codMap.get(Constants.CODPAYMENT), codService, debData.traceIdDebt,
                                originalCodPayment, dueDatesBeans, cityCode);
    
                        debData.receiptsToPay = calculateReceiptsToPay(invoiceListArray, debData.receiptsToPay);
    
                        mtDebtsResponse.setReceiptsToPay(debData.receiptsToPay);
                        
                        mtDebt.listInvoiceTotalg = listInvoiceTotal;
                        mtDebt.mtDebtsResponseg = mtDebtsResponse;
                        if (!StringUtils.equals(flagMT, FLAG_PRODUCTS_MT_VALUE_TRUE))
                            return Flux.just(mtDebt);
    
                        debData.amountRADebtMovil = listTaxTotal.stream().filter(taxTotal -> (StringUtils.equals(codService, "C")))
                                .map(taxTotal -> taxTotal.asDouble() / 100)
                                .reduce(debData.amountRADebtMovil, (accumulator, item) -> accumulator + item);
    
                        LOGGER.info("codPayment: {}", codMap.get(Constants.CODPAYMENT));
                        LOGGER.info("codService: {}", codMap.get(Constants.CODSERVICE));
                        LOGGER.info("originalCodPayment: {}", codMap.get(Constants.ORIGINALCODPAYMENT));
                        return Flux.just(mtDebt);
                    });
        }).last().map(mtDebtResponse -> {
    
            String codeStatusDebt = "S";
            String statusDebt = "No tiene deudas pendientes";
            String date = null;
            LOGGER.info("Size elements Date: {}", mtDebtResponse.listInvoiceTotalg.size());
            if (!mtDebtResponse.listInvoiceTotalg.isEmpty()) {
                date = mtDebtResponse.listInvoiceTotalg.get(0);
                Integer status = Utils.compareDateWithToday(date, DATE_FORMAT);
                statusDebt = DeudaUtil.getEstadoDeuda(status.intValue());
                codeStatusDebt = DeudaUtil.getCodigoEstadoDeuda(status.intValue());
            }
    
            mtDebtsResponse.setTraceId(debData.traceIdDebt);
            mtDebtsResponse.setInvoiceDate(date == null ? "" : date);
            mtDebtsResponse.setSumTaxTotal(String.format("%.2f", debData.sumTaxTotal));
            mtDebtsResponse.setCodeStatusDebt(codeStatusDebt);
            mtDebtsResponse.setStatusDebt(statusDebt);
            mtDebtsResponse.setReceiptsTotal(debData.receiptsTotal);
            mtDebtsResponse.setInvoiceList(debData.invoiceListNew);
            mtDebtsResponse.setDebtMovil(String.format("%.2f", debData.amountRADebtMovil));
            mtDebtsResponse.setResponseDebtHogar(mtDebtResponse.responseDebtHogarg);
            mtDebtsResponse.setResponseDebtMovil(mtDebtResponse.responseDebtMovilg);
            // Valores obtenidos del ultimo producto en el flux
            mtDebtsResponse.setReceiptsToPay(mtDebtResponse.mtDebtsResponseg.getReceiptsToPay());
            mtDebtsResponse.setInvoiceCurrency(mtDebtResponse.mtDebtsResponseg.getInvoiceCurrency());
            mtDebtsResponse.setInvoiceNumber(mtDebtResponse.mtDebtsResponseg.getInvoiceNumber());
            mtDebtsResponse.setOriginalInvoiceDate(mtDebtResponse.mtDebtsResponseg.getOriginalInvoiceDate());
            mtDebtsResponse.setCodService(mtDebtResponse.mtDebtsResponseg.getCodService());
    
            // Validar que al menos 1 producto haya respondido bien el api de deudas
            setStatusResponse(mtDebtsResponse, mtDebtResponse.listStatusRg);
    
            return mtDebtsResponse;
        });
    }