Message Detail using XML 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/144836175/cust_xml_intf_create-version-1-modificationdate-1645138041000-api-v2.png
  2. Provide processor name in Processor tab which will do all the inbound data handling.

    images/download/attachments/144836175/cust_intf_proc-version-1-modificationdate-1645138049000-api-v2.png
  3. Since this is a custom interface(for XMLs) 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/XML for ProgressiveRetailer enterprise)

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

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Orders>
    <Order>
    <BUYING_ENT>ProgressiveRetailer</BUYING_ENT>
    <SELLING_ENT>ProgressiveRetailer</SELLING_ENT>
    <ORDER_NUMBER>test12</ORDER_NUMBER>
    <CURRENCY>USD</CURRENCY>
    <BUYING_ORG>SouthRegion</BUYING_ORG>
    <SELLING_ORG>WestRegion</SELLING_ORG>
    <ITEM_NAME>158126</ITEM_NAME>
    <SHIPPED_QUANTITY>10.0</SHIPPED_QUANTITY>
    <UOM>EACH</UOM>
    <UNIT_PRICE>100.0</UNIT_PRICE>
    </Order>
    <Order>
    <BUYING_ENT>ProgressiveRetailer</BUYING_ENT>
    <SELLING_ENT>ProgressiveRetailer</SELLING_ENT>
    <ORDER_NUMBER>test13</ORDER_NUMBER>
    <CURRENCY>USD</CURRENCY>
    <BUYING_ORG>SouthRegion</BUYING_ORG>
    <SELLING_ORG>WestRegion</SELLING_ORG>
    <ITEM_NAME>213705</ITEM_NAME>
    <SHIPPED_QUANTITY>10.0</SHIPPED_QUANTITY>
    <UOM>EACH</UOM>
    <UNIT_PRICE>100.0</UNIT_PRICE>
    </Order>
    </Orders>
  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. XSD is used for marshalling and un-marshalling the data.

    // Initializations
     
    List<MessageDetail> messageDetails = new ArrayList<>();
    objmesDetailServiceImpl = new MessageDetailServiceImpl();
    TaskResult result = null;
    ModelDataService mds = Services.get(ModelDataService.class);
    com.onenetwork.platform.data.model.ModelList<Order> modelListMsg = null;
    mapTxnNoRawData = new HashMap<String, JSONArray>();
    List<Order> alstOrders = new ArrayList<Order>();
    Order order = null;
    OrderLineItem orderLineItem = null;
    int counter;
    // Iterating through file records
    try {
    JAXBContext jaxbContext = JAXBContext.newInstance(Orders.class);
     
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
     
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    Orders ordersToMarshall = new Orders();
    Orders orders = (Orders) jaxbUnmarshaller.unmarshal(message.readPayload());
    for (int i = 0; i < orders.getOrder().size(); i++) {
     
    order = new Order();
    orderLineItem = new OrderLineItem();
    /*
    Logic to create Order jaxb from the unmarshalled object
    */
    // Adding order to list
    alstOrders.add(order);
    // Forming raw data, by marshalling Orders object
    ordersToMarshall.getOrder().add(orders.getOrder().get(i));
     
    StringWriter sw = new StringWriter();
    jaxbMarshaller.marshal(ordersToMarshall, sw);
    ordersToMarshall.getOrder().clear();
     
    JSONArray arr = new JSONArray();
     
    arr.put(sw.toString());
    mapTxnNoRawData.put(order.getOrderNumber(), arr);
     
    order = null;
    orderLineItem = null;
    }
    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.getMessage());
    }
    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-XML)

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

    images/download/attachments/144836175/Msg_Det_Report_XML-version-1-modificationdate-1645138074000-api-v2.jpg