Message Detail using Flat file with a custom processor

This provides an example of enabling MessageDetail for a Custom InboundInterface with a processor.

  1. Create an inbound interface with Custom format.

    images/download/attachments/144836180/flat_inbound_1-version-1-modificationdate-1645138137000-api-v2.jpg
  2. Provide processor name in Processor tab which will do all the inbound data handling.

    images/download/attachments/144836180/flat_inbound_2-version-1-modificationdate-1645138145000-api-v2.jpg
  3. Since this is a custom interface(for Flat files) we need to create new MessageQueue, MessageSource and MessageSourcePoll configuration. This is detailed under Integration -> Message and Message Queues.

  4. External reference configuration for the queue + interface combination will be like below. (New queue in above step is created with name inbox/Flat for ProgressiveRetailer enterprise)

    #* Ref Type,* External Value,Local Value
    PLT.MessageDetail:Enable,100~inbox/Flat~ProgressiveRetailer~PTA.TestFlatFile_ORDER_IB~1.0,AllRecords,Message Detail enabled for all records
  5. The sample flat file with 2 records that will be processed is as below:

    TEST_ORDER_001CC DF0090016100Q 000000 SKU-9921 RC-MIOL+BAL.3/4 ASS 00900165002GRA 2MGB 20160425235959 20160504000000201605042359592016082409050020160824123000 000000864.000 110000000432RFR LR15AT49 CON-S-0130P1303908012016082906000020160829071500 00900161000000000001CON-S-0130 LR1585MJ GPI
     
    TEST_ORDER_002CC DF0090016100Q 000000 SKU-9922 60-MIOL+BAL.5¸ KYOWA00900165002GRA 2MGB 20160425235959 20160504000000201605042359592016082409050020160824123000 000001890.000 110000000630RFR LR15AT4A CON-S-0130P1303908012016082906000020160829071500 00900161000000000001CON-S-0130 LR1585MJ GPI
  6. Sample code to Create and Save message detail records for both Success and error scenarios is as below. Raw data is formed while iterating the file and saved. After the DB write operation, the error and success records and fetched and message detail is created. Save is done in the finally block so that even when there are exceptions message detail is updated and saved.

    // Initializations
    ModelDataService mds = Services.get(ModelDataService.class);
    MessageDetailServiceImpl objmesDetailServiceImpl = new MessageDetailServiceImpl();
    List<MessageDetail> messageDetails = new ArrayList<>();
    com.onenetwork.platform.data.model.ModelList<Order> modelListMsg = null;
    HashMap mapTxnNoRawData = new HashMap<String, JSONArray>();
    // Iterating through file records
    try {
    while ((flatFileRow = reader.nextRow()) != null) {
     
    Order order = new Order();
    OrderLineItem orderLineItem = new OrderLineItem();
    /*
    Logic to parse flat file records and populate order object goes here
    */
    alstOrders.add(order);
    // Forming raw data
    JSONArray arr = new JSONArray();
    arr.put(flatFileRow.getRawData());
     
    mapTxnNoRawData.put(order.getOrderNumber(), arr);
    }
    modelListMsg = new com.onenetwork.platform.data.model.ModelList<Order>();
    modelListMsg.setCustomModelName(Order.STANDARD_MODEL_NAME);
    modelListMsg.setValueChainId(pltUserContext.getValueChainId());
    modelListMsg.setActionName("PLT.InsertOrUpdate");
    modelListMsg.getModels().addAll(alstOrders);
    String strProcessingErrors = "";
    int counter = 0;
    com.onenetwork.platform.data.model.ModelList<Order> modelList = mds.write(modelListMsg, pltUserContext);
    for (int i = 0; i < modelListMsg.getModels().size(); i++) {
    strProcessingErrors = null;
    for (int j = 0; j < modelList.getErrors().size(); j++) {
    if (modelListMsg.getModels().get(i).getOrderNumber().equals(modelList.getModels().get(j).getOrderNumber())) {
    strProcessingErrors = modelList.getErrors().get(j).toString();
    break;
    }
    }
    counter++;
    objmesDetailServiceImpl.createMessageDetail(
    "" + counter,
    strProcessingErrors,
    modelListMsg.getModels().get(i).getOrderNumber(),
    modelListMsg.getModels().get(i).getModelType().toString(),
    mapTxnNoRawData.get(modelListMsg.getModels().get(i).getOrderNumber()).toString(),
    message,
    messageDetails,
    pltUserContext);
    }
    }
    catch (Exception e) {
    if (modelListMsg != null && modelListMsg.getModels().size() > 0) {
    updateMessgeDetailsWithError(messageDetails, modelListMsg, e.toString(), message, pltUserContext);
    }
    result = TaskResult.FAIL;
    throw new RuntimeException("Exception while processing Order(s).. " + e.toString());
    }
    finally {
    TransactionSupport.callWithNewTransaction(new java.util.concurrent.Callable<Object>() {
    @Override
    public Object call() throws Exception {
    objmesDetailServiceImpl.saveMessageDetails(messageDetails, pltUserContext);
    return null;
    }
    });
    if (result == null) {
    result = TaskResult.SUCCEED;
    }
    }
    private void updateMessgeDetailsWithError(
    List<MessageDetail> messageDetails,
    ModelList<Order> modelListMsg,
    String error,
    Message message,
    PlatformUserContext pltUserContext) {
    for (int i = 0; i < modelListMsg.getModels().size(); i++) {
    objmesDetailServiceImpl.createMessageDetail(
    "" + i + 1,
    error,
    modelListMsg.getModels().get(i).getOrderNumber(),
    modelListMsg.getModels().get(i).getModelType().toString(),
    mapTxnNoRawData.get(modelListMsg.getModels().get(i).getOrderNumber()).toString(),
    message,
    messageDetails,
    pltUserContext);
    }
    }
    }
    }
    }
  7. MessageDetailReport when added to the UIMM will be visible on UI under Message Queues menu (MessageQueues-Order-Flatfile)

    images/download/attachments/144836180/msg_det_flat_ui1-version-1-modificationdate-1645138158000-api-v2.jpg
  8. Actual MessgeDetail report will look like:

    images/download/attachments/144836180/Msg_Det_Report_Flat-version-1-modificationdate-1645138167000-api-v2.jpg