package com.gpc.tams.sync.invoice; import com.gpc.tams.model.request.InvoiceDomainFeedAuthTokenRequest; import com.gpc.tams.model.request.GcpAuthTokenRequest; import com.gpc.tams.model.invoice.domain.InvoiceDomainFeedInvoice; import com.gpc.tams.model.invoice.domain.InvoiceRecord; import com.gpc.tams.repository.communication.CommunicationUrl; import com.gpc.tams.sync.azure.monitor.AzureLogger; import com.gpc.tams.sync.azure.monitor.LogType; import com.gpc.tams.util.communication.DomainOAuthParameters; import com.gpc.tams.util.gcp.GcpJwt; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ObjectNode; import org.springframework.util.CollectionUtils; import javax.net.ssl.*; import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.util.*; public class InvoiceDomainFeedRequestWorker implements Runnable { public static final String S_HTTP_OK = "OK"; public static final int HTTP_OK = 200; public static final int HTTP_BAD_REQUEST = 400; public static final int REQUESTED_UNAUTHORIZED = 401; public static final int CLIENT_FORBIDDEN = 403; public static final int REQUESTED_INVOICE_MISSING_INFO = 404; public static final int SERVICE_ERROR = 500; public static final int UNKNOWN_RESPONSE = 9000; public static final int MAX_NUMBER_TO_RETRY_FILE = 1574; // 8 days public static int DOMAIN_FEED_MAX_TRIES; public static final String INVOICE_DOMAIN_FILES_RECORDS_PATH = "/usr/tams/database/invoice_domain_feed"; public static final String INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH = "/usr/tams/database/invoice_domain_feed/sent"; public static final String INVOICE_DOMAIN_FILES_GCP_URL_CHECK = "/invoicefeed/save"; public static final String INVOICE_DOMAIN_FILES_PROCESSING_EXT = ".p"; public static final String INVOICE_DOMAIN_FILES_RECORD_EXT = ".r"; private static final Logger logger = Logger.getLogger(InvoiceDomainFeedRequestWorker.class); public static final String SEND_STATUS_SUCCESSFUL = "SUCCESSFUL"; private final Long domainFeedWaitInterval; private List invoiceDomainFeedInvoiceList = new ArrayList(); private static volatile Map invoiceDomainFeedInvoiceRecords = new HashMap(); private boolean done = false; private CommunicationUrl communicationUrl; private InvoiceDomainFeedAuthTokenRequest invoiceDomainFeedAuthTokenRequest; private final DomainOAuthParameters domainOAuthParameters; private boolean doingRetries = false; private static volatile Map currentWorkInvoices = new HashMap(); private final String storeNumber; private static GcpAuthTokenRequest gcpAuthTokenRequest = null; private static String targetAudience; private boolean gcpOauth = false; public InvoiceDomainFeedRequestWorker(List invoiceDomainFeedInvoiceList, CommunicationUrl communicationUrl, DomainOAuthParameters domainOAuthParameters, Long domainFeedWaitInterval, Integer domainFeedMaxTries, String storeNumber) { if (!CollectionUtils.isEmpty(invoiceDomainFeedInvoiceList)) { this.invoiceDomainFeedInvoiceList.addAll(invoiceDomainFeedInvoiceList); addCurrentWorkInvoices(); } this.communicationUrl = communicationUrl; this.domainOAuthParameters = domainOAuthParameters; this.domainFeedWaitInterval = domainFeedWaitInterval; InvoiceDomainFeedRequestWorker.DOMAIN_FEED_MAX_TRIES = domainFeedMaxTries; if (StringUtils.isEmpty(storeNumber)){ this.storeNumber = StringUtils.EMPTY; } else { this.storeNumber = storeNumber; } if (communicationUrl != null && communicationUrl.getUrl() != null) { if (communicationUrl.getUrl().toLowerCase().endsWith(INVOICE_DOMAIN_FILES_GCP_URL_CHECK)) { gcpOauth = true; } } } public InvoiceDomainFeedRequestWorker(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice, CommunicationUrl communicationUrl, DomainOAuthParameters domainOAuthParameters, Long domainFeedWaitInterval, Integer domainFeedMaxTries, String storeNumber) { if (invoiceDomainFeedInvoice != null) { this.invoiceDomainFeedInvoiceList.add(invoiceDomainFeedInvoice); addCurrentWorkInvoices(); } this.communicationUrl = communicationUrl; this.domainOAuthParameters = domainOAuthParameters; this.domainFeedWaitInterval = domainFeedWaitInterval; InvoiceDomainFeedRequestWorker.DOMAIN_FEED_MAX_TRIES = domainFeedMaxTries; if (StringUtils.isEmpty(storeNumber)){ this.storeNumber = StringUtils.EMPTY; } else { this.storeNumber = storeNumber; } if (communicationUrl != null && communicationUrl.getUrl() != null) { if (communicationUrl.getUrl().toLowerCase().endsWith(INVOICE_DOMAIN_FILES_GCP_URL_CHECK)) { gcpOauth = true; } } } public InvoiceDomainFeedRequestWorker(Map invoiceDomainFeedInvoiceRecordsMap, CommunicationUrl communicationUrl, DomainOAuthParameters domainOAuthParameters, Long domainFeedWaitInterval, Integer domainFeedMaxTries, String storeNumber) { if (!CollectionUtils.isEmpty(invoiceDomainFeedInvoiceRecordsMap)) { invoiceDomainFeedInvoiceRecords.putAll(invoiceDomainFeedInvoiceRecordsMap); } this.communicationUrl = communicationUrl; this.domainOAuthParameters = domainOAuthParameters; this.domainFeedWaitInterval = domainFeedWaitInterval; InvoiceDomainFeedRequestWorker.DOMAIN_FEED_MAX_TRIES = domainFeedMaxTries; this.doingRetries = true; if (StringUtils.isEmpty(storeNumber)){ this.storeNumber = StringUtils.EMPTY; } else { this.storeNumber = storeNumber; } if (communicationUrl != null && communicationUrl.getUrl() != null) { if (communicationUrl.getUrl().toLowerCase().endsWith(INVOICE_DOMAIN_FILES_GCP_URL_CHECK)) { gcpOauth = true; } } } private synchronized boolean sendModifiedRecord(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice) { HttpsURLConnection httpsURLConnection = null; OutputStream outputStream = null; BufferedReader bufferedReader = null; boolean successful = false; boolean dataWasSent = false; String invoiceFeedData = StringUtils.EMPTY; String correlationId = invoiceDomainFeedInvoice.getCorrelationId(); if (!correlationId.startsWith(this.storeNumber)) { /* prefix with store number */ correlationId = storeNumber + "-" + correlationId; } try { invoiceFeedData = invoiceDomainFeedInvoice.getInvoiceFeedData(); if (StringUtils.isEmpty(invoiceFeedData)){ /* should not happen */ invoiceDomainFeedInvoice.setCompleted(true); logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Invalid InvoiceDomainFeedInvoice - \r\n" + "Empty data"); return false; } String authorization; String useUrl = communicationUrl.getUrl(); if (gcpOauth) { logger.debug("correlationId : " + correlationId + " using GCP oAuth : true"); String token = getGcpAuthToken(useUrl); if (!StringUtils.isEmpty(token)) { authorization = "Bearer " + token; // logger.debug("correlationId : " + correlationId + " using GCP oAuth - \r\n" + authorization); } else { invoiceDomainFeedInvoice.incrementTries(); logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Invalid token for Request - \r\n" + getLoggerPrettyJson(invoiceDomainFeedInvoice.getInvoiceFeedData())); return false; } } else { String invoiceDomainFeedAuthTokenType = getInvoiceDomainFeedAuthTokenType(); String invoiceDomainFeedAuthToken = (!StringUtils.isEmpty(invoiceDomainFeedAuthTokenType) ? getInvoiceDomainFeedAuthToken() : StringUtils.EMPTY); logger.debug("correlationId : " + correlationId + " using AWS oAuth : true"); if (StringUtils.isEmpty(invoiceDomainFeedAuthTokenType) || StringUtils.isEmpty(invoiceDomainFeedAuthToken)) { invoiceDomainFeedInvoice.incrementTries(); logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Invalid token for Request - \r\n" + getLoggerPrettyJson(invoiceDomainFeedInvoice.getInvoiceFeedData())); return false; } authorization = invoiceDomainFeedAuthTokenType + " " + invoiceDomainFeedAuthToken; } invoiceDomainFeedInvoice.incrementTries(); logger.info("correlationId : " + correlationId + " Send Request URL : " + useUrl); URL url = new URL(useUrl); httpsURLConnection = (HttpsURLConnection) url.openConnection(); httpsURLConnection.setRequestMethod("POST"); httpsURLConnection.setRequestProperty("Content-Type", "application/json; utf-8"); httpsURLConnection.setRequestProperty("Accept", invoiceDomainFeedInvoice.getApiVersion()); httpsURLConnection.setRequestProperty("User-Agent", "TAMSII/TAAP-" + storeNumber); httpsURLConnection.setRequestProperty("correlationId", correlationId); httpsURLConnection.setRequestProperty("Connection", "keep-alive"); httpsURLConnection.setRequestProperty("Keep-Alive", "timeout=60, max=120"); httpsURLConnection.setRequestProperty("Authorization", authorization); httpsURLConnection.setDoOutput(true); outputStream = httpsURLConnection.getOutputStream(); if (outputStream != null) { if (!StringUtils.isEmpty(invoiceFeedData)) { byte[] jsonInvoiceFeedDataBytes = invoiceFeedData.getBytes(StandardCharsets.UTF_8); logger.info("correlationId : " + correlationId + " Request - \r\n" + getLoggerPrettyJson(invoiceFeedData)); outputStream.write(jsonInvoiceFeedDataBytes, 0, jsonInvoiceFeedDataBytes.length); outputStream.flush(); dataWasSent = true; int responseCode = httpsURLConnection.getResponseCode(); if (responseCode < HTTP_BAD_REQUEST) { bufferedReader = new BufferedReader( new InputStreamReader(httpsURLConnection.getInputStream(), StandardCharsets.UTF_8)); } else { bufferedReader = new BufferedReader( new InputStreamReader(httpsURLConnection.getErrorStream(), StandardCharsets.UTF_8)); } StringBuilder response = new StringBuilder(); String responseLine; while ((responseLine = bufferedReader.readLine()) != null) { response.append(responseLine.trim()); } invoiceDomainFeedInvoice.setResponseCode(responseCode); ResultsOfSend resultsOfSend = new ResultsOfSend(response.toString(), responseCode); invoiceDomainFeedInvoice.setResultsOfSend(resultsOfSend); logger.info("correlationId : " + correlationId + " Response - \r\n" + getLoggerPrettyJson(response.toString())); int resultsOfSendCode = resultsOfSend.getResponseError(); if (responseCode == HTTP_OK && resultsOfSend.status.equalsIgnoreCase(S_HTTP_OK) && correlationId.equalsIgnoreCase(resultsOfSend.correlationId)) { invoiceDomainFeedInvoice.setSendStatus(SEND_STATUS_SUCCESSFUL); invoiceDomainFeedInvoice.setCompleted(true); successful = true; } else if (responseCode == HTTP_BAD_REQUEST || resultsOfSendCode == HTTP_BAD_REQUEST) { invoiceDomainFeedInvoice.setDontRetry(true); invoiceDomainFeedInvoice.setCompleted(true); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.FAILURE, responseCode,"Invoice Number:" + invoiceDomainFeedInvoice.getInvoiceNumber() + ", " + response.toString(),null,null, correlationId); } else if (resultsOfSendCode == REQUESTED_UNAUTHORIZED) { AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.YELLOW, responseCode,"Invoice Number:" + invoiceDomainFeedInvoice.getInvoiceNumber() + ", Will retry, " + response.toString(),null,null, correlationId); refreshInvoiceDomainFeedAuthToken(); } else if (resultsOfSendCode >= CLIENT_FORBIDDEN) { AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.YELLOW, responseCode, "Invoice Number:" + invoiceDomainFeedInvoice.getInvoiceNumber() + ", Will retry, " + response.toString(), null, null, correlationId); } else if (responseCode == HTTP_OK && resultsOfSend.status.equalsIgnoreCase(S_HTTP_OK) && !correlationId.equalsIgnoreCase(resultsOfSend.correlationId)) { logger.warn("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - correlationId mismatch request : " + correlationId + " response : " + resultsOfSend.correlationId); successful = true; } } else { /* should not happen */ invoiceDomainFeedInvoice.setCompleted(true); logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Invalid InvoiceDomainFeedInvoice - \r\n" + "Empty data"); } } } catch (SSLHandshakeException exception) { logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::SSLHandshakeException - Exception sending invoice domain feed ", exception); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.SSLException,418,(exception.getMessage() != null ? exception.getMessage() : exception.toString()),null,null, correlationId); } catch (SSLPeerUnverifiedException exception) { logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::SSLPeerUnverifiedException - Exception sending invoice domain feed ", exception); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.SSLException,418,(exception.getMessage() != null ? exception.getMessage() : exception.toString()),null,null, correlationId); } catch (IOException ioException) { logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::IOException - Exception sending invoice domain feed " + (ioException.getMessage() != null ? ioException.getMessage() : ioException)); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IOException,418,(ioException.getMessage() != null ? ioException.getMessage() : ioException.toString()),null,null, correlationId); try { if (httpsURLConnection != null) { int responseCode = httpsURLConnection.getResponseCode(); if (responseCode == REQUESTED_UNAUTHORIZED) { refreshInvoiceDomainFeedAuthToken(); } else if (responseCode == HTTP_BAD_REQUEST) { if (dataWasSent) { invoiceDomainFeedInvoice.setCompleted(true); } else { logger.info("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::IOException response code: " + responseCode + " Unsent Request, will retry - \r\n" + getLoggerPrettyJson(invoiceFeedData)); } logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::IOException - Exception sending invoice domain feed responseCode : " + responseCode); } } } catch (IOException ioException2) { // High chance connection was reset or closed - expected logger.debug("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::IOException - Exception checking for HttpsURLConnection responseCode after..." + (ioException2.getMessage() != null ? ioException2.getMessage() : ioException2)); } } catch (Exception exception) { // invoiceDomainFeedInvoice.setCompleted(true); logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Exception sending invoice domain feed ", exception); } if (httpsURLConnection != null) { try { if (outputStream != null) { outputStream.close(); } if (bufferedReader != null) { bufferedReader.close(); } httpsURLConnection.disconnect(); } catch (IOException ioException) { logger.error("correlationId : " + correlationId + " InvoiceDomainFeedRequestWorker::sendModifiedRecord - Exception closing connection " + ioException); } } return successful; } private String getPrettyJson(String jsonString) { String invoiceFeedDataPrettyJson; try { ObjectMapper mapper = new ObjectMapper(); Object jsonObject = mapper.readValue(jsonString, Object.class); invoiceFeedDataPrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject); } catch (Exception exception) { return jsonString; } return invoiceFeedDataPrettyJson; } private String getLoggerPrettyJson(String jsonString) { String loggerJsonString; if (!InvoiceDomainFeedInvoice.debugTesting) { loggerJsonString = getMinLoggerJson(jsonString); if (!StringUtils.isEmpty(loggerJsonString)) { return getPrettyJson(loggerJsonString); } } return getPrettyJson(jsonString); } @Override public void run() { try { if (communicationUrl == null || StringUtils.isEmpty(communicationUrl.getUrl())) { logger.error("InvoiceDomainFeedRequestWorker::run - Invalid or missing URL."); return; } if (doingRetries) { processRecordFiles(); return; } while (!done) { ListIterator listIterator = invoiceDomainFeedInvoiceList.listIterator(); while (listIterator.hasNext()) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoice = listIterator.next(); if (invoiceDomainFeedInvoice != null) { if (invoiceDomainFeedInvoice.isSaveForRetry() && writeInvoiceRecord(invoiceDomainFeedInvoice, false)) { listIterator.remove(); removeInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice); continue; } if (!invoiceDomainFeedInvoice.isCompleted() && invoiceDomainFeedInvoice.getTries() < DOMAIN_FEED_MAX_TRIES) { boolean sendStatus = sendModifiedRecord(invoiceDomainFeedInvoice); if (sendStatus || invoiceDomainFeedInvoice.isCompleted()) { listIterator.remove(); removeInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice); if (sendStatus) { saveSentInvoiceRecord(invoiceDomainFeedInvoice); } } } else { /* done trying */ if (invoiceDomainFeedInvoice.getTries() >= DOMAIN_FEED_MAX_TRIES) { listIterator.remove(); removeInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice); logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::run Failed all retries for sending Request - \r\n" + getLoggerPrettyJson(invoiceDomainFeedInvoice.getInvoiceFeedData())); if (!invoiceDomainFeedInvoice.isDontRetry()) { invoiceDomainFeedInvoice.resetTrackingValues(); writeInvoiceRecord(invoiceDomainFeedInvoice, false); } else { logger.info("InvoiceDomainFeedRequestWorker::run Has dontRetry flag set for invoice : " + invoiceDomainFeedInvoice.getInvoiceNumber().toString()); } } } } else { listIterator.remove(); /* should not happen */ logger.error("InvoiceDomainFeedRequestWorker::run Failed for invalid InvoiceDomainFeedInvoice - \r\n" + "is NULL"); } } if (!done && !invoiceDomainFeedInvoiceList.isEmpty()) { delay(); } else { /* all finished */ return; } } } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker::run - Exception thread " + exception); } } private synchronized void processRecordFiles() { boolean deleteFile = false; List listKeyInvoiceNumbers = null; if (!done && !CollectionUtils.isEmpty(invoiceDomainFeedInvoiceRecords)) { int successCount = 0; int totalInvoices = invoiceDomainFeedInvoiceRecords.size(); listKeyInvoiceNumbers = new ArrayList(invoiceDomainFeedInvoiceRecords.keySet()); while (!CollectionUtils.isEmpty(listKeyInvoiceNumbers)) { ListIterator listIterator = listKeyInvoiceNumbers.listIterator(); while (listIterator.hasNext()) { deleteFile = false; String invoiceNumber = listIterator.next(); if (invoiceNumber != null) { File file = invoiceDomainFeedInvoiceRecords.get(invoiceNumber); InvoiceDomainFeedInvoice invoiceDomainFeedInvoice = readInvoiceRecord(file); if (invoiceDomainFeedInvoice != null && !invoiceDomainFeedInvoice.isDontRetry()) { boolean sendStatus = sendModifiedRecord(invoiceDomainFeedInvoice); if (sendStatus) { listIterator.remove(); deleteFile = true; removeFromRecordFileList(invoiceNumber); saveSentInvoiceRecord(invoiceDomainFeedInvoice); successCount++; } else if (invoiceDomainFeedInvoice.getRetryInvoiceRecordAttempts() >= MAX_NUMBER_TO_RETRY_FILE) { listIterator.remove(); deleteFile = true; invoiceDomainFeedInvoice.setDontRetry(true); removeFromRecordFileList(invoiceNumber); logger.error("InvoiceDomainFeedRequestWorker::processRecordFiles Exceeded retry max limit for file : " + file.getName()); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.RED,418, "InvoiceDomainFeedRequestWorker::processRecordFiles Exceeded retry limit for invoice: " + invoiceNumber + " , will not retry again.",null,null,invoiceDomainFeedInvoice.getCorrelationId()); } else if (invoiceDomainFeedInvoice.getTries() >= DOMAIN_FEED_MAX_TRIES) { invoiceDomainFeedInvoice.incrementRetryInvoiceRecordAttempts(); logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::processRecordFiles Failed all retries for sending Request - \r\n" + getLoggerPrettyJson(invoiceDomainFeedInvoice.getInvoiceFeedData())); listIterator.remove(); writeInvoiceRecord(invoiceDomainFeedInvoice, true); removeFromRecordFileList(invoiceNumber); } else if (invoiceDomainFeedInvoice.isDontRetry() || invoiceDomainFeedInvoice.isCompleted()) { listIterator.remove(); removeFromRecordFileList(invoiceNumber); if (invoiceDomainFeedInvoice.isDontRetry()) { logger.info("InvoiceDomainFeedRequestWorker::processRecordFiles Has dontRetry flag set for file : " + file.getName()); } else { logger.info("InvoiceDomainFeedRequestWorker::processRecordFiles Failed retries for file : " + file.getName()); } deleteFile = true; } else { writeInvoiceRecord(invoiceDomainFeedInvoice, true); if (invoiceDomainFeedInvoice.isDontRetry()) { listIterator.remove(); removeFromRecordFileList(invoiceNumber); deleteFile = true; } } } else { listIterator.remove(); removeFromRecordFileList(invoiceNumber); if (invoiceDomainFeedInvoice == null) { logger.error("InvoiceDomainFeedRequestWorker::processRecordFiles invalid file : " + file.getName()); } else { logger.info("InvoiceDomainFeedRequestWorker::processRecordFiles Has dontRetry flag set for file : " + file.getName()); } deleteFile = true; } try { if (deleteFile && file.exists()) { if (!deleteInvoiceDomainFeedRecordFile(file)) { logger.error("InvoiceDomainFeedRequestWorker::processRecordFiles Failed to delete file : " + file.getName()); } else { logger.info("InvoiceDomainFeedRequestWorker::processRecordFiles deleted file : " + file.getName()); } } } catch (SecurityException securityException) { logger.error("InvoiceDomainFeedRequestWorker.processRecordFiles: SecurityException ", securityException); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.processRecordFiles: Exception ", exception); } } else { listIterator.remove(); } } if (!done && !listKeyInvoiceNumbers.isEmpty()) { delay(); } else { /* all finished */ doingRetries = false; if (totalInvoices == successCount) { AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.GREEN,200, "InvoiceDomainFeedRequestWorker::processRecordFiles successfully processed invoices: " + successCount, null,null,null); } else { AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.RED,418, "InvoiceDomainFeedRequestWorker::processRecordFiles processed " + successCount + " invoice(s) out of " + totalInvoices ,null,null,null); } return; } } } } private synchronized void delay() { try { wait(domainFeedWaitInterval); } catch (IllegalMonitorStateException exception) { logger.error("InvoiceDomainFeedRequestWorker::delay - IllegalMonitorStateException " + exception); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker::delay - Exception " + exception); } } public boolean isKillThread() { return done; } public void killThread() { this.done = true; } public List getInvoiceDomainFeedInvoiceList() { return invoiceDomainFeedInvoiceList; } private synchronized boolean writeInvoiceRecord(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice, boolean doUpdate) { String invoiceRecordJson = StringUtils.EMPTY; if (doUpdate) { return updateProcessingInvoiceRecord(invoiceDomainFeedInvoice); } try { File path = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (!hasPath) { hasPath = path.mkdir(); } if (invoiceDomainFeedInvoice != null && hasPath) { String invoiceNumber = invoiceDomainFeedInvoice.getInvoiceNumber().toString(); if (!StringUtils.isEmpty(invoiceDomainFeedInvoice.getInvoiceFeedData())) { InvoiceRecord invoiceRecord = new InvoiceRecord(invoiceDomainFeedInvoice, communicationUrl); invoiceRecord.setDontRetry(invoiceDomainFeedInvoice.isDontRetry()); String hasInvoiceRecordJson = getInvoiceRecordJson(invoiceRecord); invoiceRecordJson = !StringUtils.isEmpty(hasInvoiceRecordJson) ? getPrettyJson(hasInvoiceRecordJson) : StringUtils.EMPTY; if (!StringUtils.isEmpty(invoiceRecordJson)) { File newFile = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_RECORD_EXT); if (newFile.exists()) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoiceFile = readInvoiceRecord(newFile); if (invoiceDomainFeedInvoiceFile != null && invoiceDomainFeedInvoiceFile.getLastModifiedDate().compareTo(invoiceDomainFeedInvoice.getLastModifiedDate()) > 0) { logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - has newer record file : " + newFile.getName()); return true; } } else if (!newFile.createNewFile()) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - Unable to create record file : " + newFile.getName()); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.FAILURE,418, "InvoiceDomainFeedRequestWorker::writeInvoiceRecord - Unable to create record file: " + newFile.getName(),null,null, invoiceDomainFeedInvoice.getCorrelationId()); if (invoiceDomainFeedInvoice.isSaveForRetry()) { logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - Try sending record file : " + newFile.getName()); invoiceDomainFeedInvoice.clearSaveForRetry(); } return false; } ObjectMapper mapperWrite = new ObjectMapper(); invoiceRecord.setLastRetryDate(new Date().getTime()); mapperWrite.writeValue(newFile, invoiceRecord); logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - Wrote record file : " + newFile.getName()); return true; } } } } catch (IllegalArgumentException illegalArgumentException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - IllegalArgumentException writing record - \r\n" + invoiceRecordJson + "\r\n" + illegalArgumentException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IllegalArgumentException,418,(illegalArgumentException.getMessage() != null ? illegalArgumentException.getMessage() : illegalArgumentException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (IOException ioException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::writeInvoiceRecord - IOException writing record - \r\n" + invoiceRecordJson + "\r\n" + ioException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IOException,418,(ioException.getMessage() != null ? ioException.getMessage() : ioException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (SecurityException securityException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.writeInvoiceRecord: SecurityException writing record - \r\n" + invoiceRecordJson + "\r\n" + securityException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.SecurityException,418,(securityException.getMessage() != null ? securityException.getMessage() : securityException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (Exception exception) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.writeInvoiceRecord: Exception writing record - \r\n" + invoiceRecordJson + "\r\n" + exception); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.Exception,418,(exception.getMessage() != null ? exception.getMessage() : exception.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } return false; } private synchronized boolean saveSentInvoiceRecord(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice) { String invoiceRecordJson = StringUtils.EMPTY; try { File path = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (!hasPath) { hasPath = path.mkdir(); } if (hasPath) { path = new File(INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH); hasPath = path.exists(); if (!hasPath) { hasPath = path.mkdir(); } } if (invoiceDomainFeedInvoice != null && hasPath && !invoiceDomainFeedInvoice.isDontRetry() && !invoiceDomainFeedInvoice.isSyncRecord()) { invoiceDomainFeedInvoice.setSyncRecord(true); invoiceDomainFeedInvoice.resetSyncTrackingValues(); String invoiceNumber = invoiceDomainFeedInvoice.getInvoiceNumber().toString(); if (!StringUtils.isEmpty(invoiceDomainFeedInvoice.getInvoiceFeedData())) { InvoiceRecord invoiceRecord = new InvoiceRecord(invoiceDomainFeedInvoice, communicationUrl); String hasInvoiceRecordJson = getInvoiceRecordJson(invoiceRecord); invoiceRecordJson = !StringUtils.isEmpty(hasInvoiceRecordJson) ? getPrettyJson(hasInvoiceRecordJson) : StringUtils.EMPTY; if (!StringUtils.isEmpty(invoiceRecordJson)) { File newFile = new File(INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_RECORD_EXT); if (newFile.exists()) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoiceFile = readInvoiceRecord(newFile); if (invoiceDomainFeedInvoiceFile != null && invoiceDomainFeedInvoiceFile.getLastModifiedDate().compareTo(invoiceDomainFeedInvoice.getLastModifiedDate()) > 0) { logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - has newer record file : " + newFile.getName()); return true; } } else if (!newFile.createNewFile()) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - Unable to create record file : " + newFile.getName()); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.FAILURE,418, "InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - Unable to create record file: " + newFile.getName(),null,null, invoiceDomainFeedInvoice.getCorrelationId()); return false; } ObjectMapper mapperWrite = new ObjectMapper(); invoiceRecord.setLastRetryDate(new Date().getTime()); mapperWrite.writeValue(newFile, invoiceRecord); logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - Wrote record file : " + newFile.getName()); return true; } } } } catch (IllegalArgumentException illegalArgumentException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - IllegalArgumentException writing record - \r\n" + invoiceRecordJson + "\r\n" + illegalArgumentException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IllegalArgumentException,418,(illegalArgumentException.getMessage() != null ? illegalArgumentException.getMessage() : illegalArgumentException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (IOException ioException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::saveSentInvoiceRecord - IOException writing record - \r\n" + invoiceRecordJson + "\r\n" + ioException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IOException,418,(ioException.getMessage() != null ? ioException.getMessage() : ioException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (SecurityException securityException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.saveSentInvoiceRecord: SecurityException writing record - \r\n" + invoiceRecordJson + "\r\n" + securityException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.SecurityException,418,(securityException.getMessage() != null ? securityException.getMessage() : securityException.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } catch (Exception exception) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.saveSentInvoiceRecord: Exception writing record - \r\n" + invoiceRecordJson + "\r\n" + exception); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.Exception,418,(exception.getMessage() != null ? exception.getMessage() : exception.toString()),null,null,invoiceDomainFeedInvoice.getCorrelationId()); } return false; } private synchronized boolean updateProcessingInvoiceRecord(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice) { String invoiceRecordJson = StringUtils.EMPTY; try { File path = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (!hasPath) { hasPath = path.mkdir(); } if (invoiceDomainFeedInvoice != null && hasPath) { String invoiceNumber = invoiceDomainFeedInvoice.getInvoiceNumber().toString(); if (!StringUtils.isEmpty(invoiceDomainFeedInvoice.getInvoiceFeedData())) { InvoiceRecord invoiceRecord = new InvoiceRecord(invoiceDomainFeedInvoice, communicationUrl); invoiceRecord.setDontRetry(invoiceDomainFeedInvoice.isDontRetry()); String hasInvoiceRecordJson = getInvoiceRecordJson(invoiceRecord); invoiceRecordJson = !StringUtils.isEmpty(hasInvoiceRecordJson) ? getPrettyJson(hasInvoiceRecordJson) : StringUtils.EMPTY; if (!StringUtils.isEmpty(invoiceRecordJson)) { File processingFile = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_PROCESSING_EXT); File newFile = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_RECORD_EXT); if (newFile.exists()) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoiceFile = readInvoiceRecord(newFile); if (invoiceDomainFeedInvoiceFile != null && invoiceDomainFeedInvoiceFile.getLastModifiedDate().compareTo(invoiceDomainFeedInvoice.getLastModifiedDate()) > 0) { logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - has newer record file : " + newFile.getName()); invoiceDomainFeedInvoice.setDontRetry(true); return true; } } else if (!processingFile.exists()) { invoiceDomainFeedInvoice.setDontRetry(true); logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - Unable to update processing record file, file missing or deleted : " + processingFile.getName()); return false; } if (processingFile.canWrite()) { ObjectMapper mapperWrite = new ObjectMapper(); mapperWrite.writeValue(processingFile, invoiceRecord); logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - Updated processing record file : " + processingFile.getName()); } else { invoiceDomainFeedInvoice.setDontRetry(true); logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - has invalid file permissions : " + processingFile.getName()); return false; } if (invoiceDomainFeedInvoice.getTries() >= DOMAIN_FEED_MAX_TRIES) { if (processingFile.renameTo(newFile)) { logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - rename processing record file : " + processingFile.getName() + " To : " + newFile.getName()); } else { /* Should not happen - the next retry of file will do cleanup of processing file */ logger.info("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - unable to rename processing record file : " + processingFile.getName() + " To : " + newFile.getName()); } } return true; } } } } catch (IllegalArgumentException illegalArgumentException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - IllegalArgumentException updating record - \r\n" + invoiceRecordJson + "\r\n" + illegalArgumentException); } catch (IOException ioException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker::updateProcessingInvoiceRecord - IOException updating record - \r\n" + invoiceRecordJson + "\r\n" + ioException); } catch (SecurityException securityException) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.updateProcessingInvoiceRecord: SecurityException updating record - \r\n" + invoiceRecordJson + "\r\n" + securityException); } catch (Exception exception) { logger.error("correlationId : " + invoiceDomainFeedInvoice.getCorrelationId() + " InvoiceDomainFeedRequestWorker.updateProcessingInvoiceRecord: Exception updating record - \r\n" + invoiceRecordJson + "\r\n" + exception); } return false; } private synchronized InvoiceDomainFeedInvoice readInvoiceRecord(File file) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoice = null; try { if (file != null && file.exists()) { InvoiceRecord invoiceRecord = new ObjectMapper().readValue(file, InvoiceRecord.class); if (invoiceRecord != null && !StringUtils.isEmpty(invoiceRecord.getPayload()) ){ invoiceDomainFeedInvoice = new InvoiceDomainFeedInvoice(invoiceRecord); return invoiceDomainFeedInvoice; } } } catch (IllegalArgumentException illegalArgumentException) { logger.error("InvoiceDomainFeedRequestWorker.readInvoiceRecord: IllegalArgumentException reading file : " + file.getName() + "\r\n" + illegalArgumentException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IllegalArgumentException,418,(illegalArgumentException.getMessage() != null ? illegalArgumentException.getMessage() : illegalArgumentException.toString()),null,null,null); deleteInvoiceDomainFeedRecordFile(file); } catch (IOException ioException) { logger.error("InvoiceDomainFeedRequestWorker.readInvoiceRecord: IOException reading file : " + file.getName() + "\r\n" + ioException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.IllegalArgumentException,418,(ioException.getMessage() != null ? ioException.getMessage() : ioException.toString()),null,null,null); } catch (SecurityException securityException) { logger.error("InvoiceDomainFeedRequestWorker.readInvoiceRecord: SecurityException reading file : " + file.getName() + "\r\n" + securityException); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.SecurityException,418,(securityException.getMessage() != null ? securityException.getMessage() : securityException.toString()),null,null,null); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.readInvoiceRecord: Exception reading file : " + file.getName() + "\r\n" + exception); AzureLogger.write(LogType.Feature.InvoiceDomain,storeNumber, LogType.Status.Exception,418,(exception.getMessage() != null ? exception.getMessage() : exception.toString()),null,null,null); } return null; } public static synchronized boolean deleteInvoiceDomainFeedRecordFile(String invoiceNumber) { try { if (!StringUtils.isEmpty(invoiceNumber)) { File path = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH); boolean hasPath = path.exists(); if (hasPath) { File file = new File(INVOICE_DOMAIN_FILES_RECORDS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_RECORD_EXT); if (file.exists()) { deleteInvoiceDomainFeedRecordFile(file); } } deleteInvoiceDomainFeedRecordResyncFile(invoiceNumber); return true; } } catch (SecurityException securityException) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordFile: SecurityException ", securityException); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordFile: Exception ", exception); } return false; } private static synchronized boolean deleteInvoiceDomainFeedRecordResyncFile(String invoiceNumber) { try { if (!StringUtils.isEmpty(invoiceNumber)) { File path = new File(INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH); boolean hasPath = path.exists(); if (hasPath) { File file = new File(INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH + "/" + invoiceNumber + INVOICE_DOMAIN_FILES_RECORD_EXT); if (file.exists()) { return deleteInvoiceDomainFeedRecordFile(file); } return true; } } } catch (SecurityException securityException) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordResyncFile: SecurityException ", securityException); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordResyncFile: Exception ", exception); } return false; } public static synchronized boolean deleteInvoiceDomainFeedRecordFile(File file) { try { if (file != null) { if (file.getPath().contains(INVOICE_DOMAIN_FILES_RECORDS_PATH) || file.getPath().contains(INVOICE_DOMAIN_FILES_RECORDS_SUCCESS_PATH)) { if (file.exists()) { if (file.canWrite()) { return file.delete(); } else { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordFile: Record file has invalid permissions!!! : " + file.getName()); } } } } } catch (SecurityException securityException) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordFile: SecurityException ", securityException); } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.deleteInvoiceDomainFeedRecordFile: Exception ", exception); } return false; } private synchronized void addCurrentWorkInvoices() { if (!CollectionUtils.isEmpty(invoiceDomainFeedInvoiceList)) { ListIterator listIterator = invoiceDomainFeedInvoiceList.listIterator(); while (listIterator.hasNext()) { InvoiceDomainFeedInvoice invoiceDomainFeedInvoice = listIterator.next(); if (invoiceDomainFeedInvoice != null) { addInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice); } } } } public static synchronized boolean addInvoiceDomainFeedInvoiceNumber(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice) { return addRemoveInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice, true); } public static synchronized boolean removeInvoiceDomainFeedInvoiceNumber(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice) { return addRemoveInvoiceDomainFeedInvoiceNumber(invoiceDomainFeedInvoice, false); } private static synchronized boolean addRemoveInvoiceDomainFeedInvoiceNumber(InvoiceDomainFeedInvoice invoiceDomainFeedInvoice, boolean add) { try { if (invoiceDomainFeedInvoice != null) { Integer invoiceNumber = invoiceDomainFeedInvoice.getInvoiceNumber(); if (invoiceNumber != null) { if (add) { if (!hasInvoiceDomainFeedInvoiceNumber(invoiceNumber.toString())) return (currentWorkInvoices.put(invoiceNumber.toString(), invoiceNumber) != null); } else { return (currentWorkInvoices.remove(invoiceNumber.toString()) != null); } } else { logger.error("InvoiceDomainFeedRequestWorker.addRemoveInvoiceDomainFeedInvoiceNumber : null invoiceNumber"); } } } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.addRemoveInvoiceDomainFeedInvoiceNumber: Exception ", exception); } return false; } private synchronized void removeFromRecordFileList(String invoiceNumber) { if (!StringUtils.isEmpty(invoiceNumber)) { invoiceDomainFeedInvoiceRecords.remove(invoiceNumber); } } public static synchronized boolean processingInvoiceDomainFeedInvoiceNumber(String invoiceNumber) { if (hasInvoiceDomainFeedInvoiceNumber(invoiceNumber) || hasInvoiceDomainFeedProcessingFile(invoiceNumber)) { return true; } return false; } public static synchronized boolean hasInvoiceDomainFeedInvoiceNumber(String invoiceNumber) { try { if (!StringUtils.isEmpty(invoiceNumber) && !CollectionUtils.isEmpty(currentWorkInvoices)) { return (currentWorkInvoices.get(invoiceNumber) != null); } } catch (Exception exception) { logger.error("InvoiceDomainFeedRequestWorker.currentWorkInvoices: Exception ", exception); } return false; } public static synchronized boolean hasInvoiceDomainFeedProcessingFile(String invoiceNumber) { if (!StringUtils.isEmpty(invoiceNumber)) { return (invoiceDomainFeedInvoiceRecords.get(invoiceNumber) != null); } return false; } public synchronized static boolean isDoingRetries() { return (!CollectionUtils.isEmpty(invoiceDomainFeedInvoiceRecords)); } private synchronized String refreshGcpInvoiceDomainFeedAuthToken() { if (gcpAuthTokenRequest == null) { return getGcpAuthToken(communicationUrl.getUrl()); } return gcpAuthTokenRequest.refreshToken(); } private synchronized String refreshInvoiceDomainFeedAuthToken() { if (gcpOauth) { return refreshGcpInvoiceDomainFeedAuthToken(); } if (invoiceDomainFeedAuthTokenRequest == null) { invoiceDomainFeedAuthTokenRequest = new InvoiceDomainFeedAuthTokenRequest(domainOAuthParameters, storeNumber); } return invoiceDomainFeedAuthTokenRequest.refreshToken(); } private synchronized String getInvoiceDomainFeedAuthToken() { if (gcpOauth) { return refreshGcpInvoiceDomainFeedAuthToken(); } if (invoiceDomainFeedAuthTokenRequest == null) { invoiceDomainFeedAuthTokenRequest = new InvoiceDomainFeedAuthTokenRequest(domainOAuthParameters, storeNumber); } return invoiceDomainFeedAuthTokenRequest.getToken(); } private synchronized String getInvoiceDomainFeedAuthTokenType() { if (invoiceDomainFeedAuthTokenRequest == null) { invoiceDomainFeedAuthTokenRequest = new InvoiceDomainFeedAuthTokenRequest(domainOAuthParameters, storeNumber); } if (invoiceDomainFeedAuthTokenRequest != null) { return invoiceDomainFeedAuthTokenRequest.getTokenType(); } return StringUtils.EMPTY; } public CommunicationUrl getCommunicationUrl() { return communicationUrl; } public void setCommunicationUrl(CommunicationUrl communicationUrl) { this.communicationUrl = communicationUrl; } public String getInvoiceRecordJson(InvoiceRecord invoiceRecord) { String invoiceRecordJson = StringUtils.EMPTY; if (invoiceRecord != null) { try { ObjectMapper mapper = new ObjectMapper(); invoiceRecordJson = mapper.writeValueAsString(invoiceRecord); } catch (Exception exception) { logger.error("correlationId : " + invoiceRecord.getCorrelationId() + " InvoiceDomainFeedInvoice::getInvoiceRecordJson - Exception generating JSON ", exception); return StringUtils.EMPTY; } } return invoiceRecordJson; } private String getMinLoggerJson(final String payload) { /* This will limit the signature size that's logged */ try { String logPayload = payload; ObjectMapper mapper = new ObjectMapper(); JsonNode parentJsonNode = mapper.readTree(logPayload); if (parentJsonNode != null) { ObjectNode invoiceHeaderObjectNode = ((ObjectNode) parentJsonNode.get("invoiceHeader")); if (invoiceHeaderObjectNode != null) { String invoiceSignature = (parentJsonNode.get("invoiceHeader")).get("invoiceSignature") != null ? (parentJsonNode.get("invoiceHeader")).get("invoiceSignature").asText() : StringUtils.EMPTY; if (!StringUtils.isEmpty(invoiceSignature)) { String subInvoiceSignature; if (invoiceSignature.length() > 20) { subInvoiceSignature = invoiceSignature.substring(0, 20); } else { subInvoiceSignature = invoiceSignature; } if (!StringUtils.isEmpty(subInvoiceSignature)) { subInvoiceSignature += " ..."; ((ObjectNode) parentJsonNode.get("invoiceHeader")).put("invoiceSignature", subInvoiceSignature); return parentJsonNode.toString(); } } } } } catch (Exception exception) { logger.warn("InvoiceDomainFeedRequestWorker::getMinLoggerJson Exception " + exception); } return null; } private synchronized String getGcpAuthToken(String hostName) { /* * - Path for service key json file * - Audience will use the base of host name, set targetAudience TRUE ! * */ String correlationId = UUID.randomUUID().toString(); try { if (StringUtils.isEmpty(targetAudience)) { /* get target audience from host name */ if (hostName.toLowerCase().contains(INVOICE_DOMAIN_FILES_GCP_URL_CHECK)) { int index = hostName.toLowerCase().indexOf(INVOICE_DOMAIN_FILES_GCP_URL_CHECK); if (index > 0) { targetAudience = hostName.toLowerCase().substring(0, index); logger.info(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - using oAuth2 with target audience: " + targetAudience); } else { logger.warn(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - unable to determine target audience"); AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.RED, 418, "InvoiceDomainFeedRequestWorker::getGcpAuthToken - unable to determine target audience ", null, hostName, correlationId); targetAudience = null; } } else { logger.warn(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - unable to determine target audience"); AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.RED, 418, "InvoiceDomainFeedRequestWorker::getGcpAuthToken - unable to determine target audience ", null, hostName, correlationId); targetAudience = null; return null; } } if (gcpAuthTokenRequest == null) { GcpJwt gcpJwt = new GcpJwt(this.domainOAuthParameters.getGcpServiceKey(), targetAudience, true); gcpAuthTokenRequest = new GcpAuthTokenRequest(gcpJwt, storeNumber, LogType.Feature.InvoiceDomain); } return gcpAuthTokenRequest.getToken(); } catch (IllegalArgumentException illegalArgumentException) { logger.error(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - IllegalArgumentException sending invoice ", illegalArgumentException); AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.IllegalArgumentException, 418, "IllegalArgumentException getGcpAuthToken " + (illegalArgumentException.getMessage() != null ? illegalArgumentException.getMessage() : illegalArgumentException), null, null, correlationId); } catch (InvalidKeyException invalidKeyException) { logger.error(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - InvalidKeyException sending invoice ", invalidKeyException); AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.Exception, 418, "InvalidKeyException getGcpAuthToken " + (invalidKeyException.getMessage() != null ? invalidKeyException.getMessage() : invalidKeyException), null, null, correlationId); } catch (Exception exception) { logger.error(correlationId + " InvoiceDomainFeedRequestWorker::getGcpAuthToken - Exception sending invoice ", exception); AzureLogger.write(LogType.Feature.InvoiceDomain, storeNumber, LogType.Status.Exception,418, "Exception getGcpAuthToken " + (exception.getMessage() != null ? exception.getMessage() : exception), null, null, correlationId); } return null; } private class ResultsOfSend { String status = StringUtils.EMPTY; String errorCode = StringUtils.EMPTY; String correlationId = StringUtils.EMPTY; String payload = StringUtils.EMPTY; String message = StringUtils.EMPTY; String timeStamp = StringUtils.EMPTY; String debugMessage = StringUtils.EMPTY; int responseError = -1; private final String response; public String getStatus() { return status; } public String getErrorCode() { return errorCode; } public String getCorrelationId() { return correlationId; } public String getPayload() { return payload; } public String getMessage() { return message; } public String getTimeStamp() { return timeStamp; } public String getDebugMessage() { return debugMessage; } public int responseCode = -1; public int getResponseCode() { return responseCode; } public int getResponseError() { return responseError; } public ResultsOfSend(String response, int responseCode) { this.response = response; this.responseCode = responseCode; init(); } private void init() { try { ObjectMapper mapper = new ObjectMapper(); JsonNode responseJsonNode = mapper.readTree(response); if (responseJsonNode != null) { status = responseJsonNode.get("status") != null ? responseJsonNode.get("status").asText() : StringUtils.EMPTY; errorCode = responseJsonNode.get("errorCode") != null ? responseJsonNode.get("errorCode").asText() : StringUtils.EMPTY; correlationId = responseJsonNode.get("correlationId") != null ? responseJsonNode.get("correlationId").asText() : StringUtils.EMPTY; payload = responseJsonNode.get("payload") != null ? responseJsonNode.get("payload").asText() : StringUtils.EMPTY; message = responseJsonNode.get("message") != null ? responseJsonNode.get("message").asText() : StringUtils.EMPTY; timeStamp = responseJsonNode.get("timeStamp") != null ? responseJsonNode.get("timeStamp").asText() : StringUtils.EMPTY; debugMessage = responseJsonNode.get("debugMessage") != null ? responseJsonNode.get("debugMessage").asText() : StringUtils.EMPTY; if (!StringUtils.isEmpty(errorCode)) { Integer value = Integer.valueOf(errorCode.trim()); if (value != null) { responseError = value.intValue(); } } } } catch (NumberFormatException numberFormatException) { logger.error("InvoiceDomainFeedRequestWorker::ResultsOfSend request - NumberFormatException value=" + errorCode + " " + numberFormatException); responseError = UNKNOWN_RESPONSE; } catch (Exception exception) { responseError = UNKNOWN_RESPONSE; logger.error("InvoiceDomainFeedRequestWorker::ResultsOfSend request - Exception " + exception); } if (StringUtils.isEmpty(status) || StringUtils.isEmpty(correlationId)) { if (responseCode >= 400){ responseError = responseCode; logger.error("InvoiceDomainFeedRequestWorker::ResultsOfSend request - Response received with response code: " + responseCode +" - \r\n" + response); } else { responseError = UNKNOWN_RESPONSE; logger.error("InvoiceDomainFeedRequestWorker::ResultsOfSend request - Unknown response received with response code: " + responseCode + " - \r\n" + response); } } else { if (!StringUtils.isEmpty(status) && status.equalsIgnoreCase("BAD_REQUEST")) { responseError=HTTP_BAD_REQUEST; } } } } }