FoodBroker project: Handle absence of partner rates

In the previous chapter, you inserted the XML file that contains the partner rates into your Mapping Flow. You wrote a Custom Function that loads the file into a raw-data (class V) container, and then you used that Custom Function in conjunction with a special decision path step to provide the MB_extractor DML Block with the expected information.

When coding the Custom Function in C programming language, exceptions were handled using null or absent symbolic for the returned values. Such management does not distinguish between empty or non-existent files and technical difficulties in loading a present and full file.

A more accurate process would:

  • Return absent when the supplied file does not exist or is empty
  • Return null when the supplied filename is absent or null
  • Signal a system error when the function is not able to load the file for technical reasons.

Let’s rework the code for LoadFile:

int LoadFile(EXE_HANDLE hCtx, EXE_hRegister hFileContents,
                              EXE_hRegister hFileName)
{
char szFileName[MAXPATH + 1];
FILE *pFile;
char *pBuffer;
size_t ulSize;

    /* Reject calls with an empty filename */
    if (xibrt_isNull(hCtx, hFilename) || xibrt_isNull(hCtx, hFilename))
    {
        xibrt_setNull(hCtx, hFileContents);
        return XIBRT_SUCCESS;
    }
    /* Extract filename arguments
     * The contents of hFileName is cloned into a static buffer
     * theoricaly large enough to contain the whole filename.
     * Only a loss of data is possible here (truncated filename)
     * that occurs only when the filename is not

     * filesystem compatible.
     */

    xibrt_getString(hCtx, hFileName, sizeof(szFilename), szFilename);

    /* Try to open the file and return ‘absent’ on failure */
    pFile = fopen(szFilename, "r");
    if (!pFile)
    {
        if (errno != ENOENT)
        {
           return XIBRT_SYSFATAL;
        }
        xibrt_setAbsent(hCtx, hFileContents);
        return XIBRT_SUCCESS;
    }
    /* Collect file size and allocate room for contents,
       then load the file into the buffer and close it */
    ulSize = fseek(pFile, 0, SEEK_END);
    fseek(pFile, 0, SEEK_SET);
    if (ulSize == 0)
    {
        xibrt_setAbsent(hCtx, hFileContents);
        return XIBRT_SUCCESS;
    }
    pBuffer = (char *) malloc(ulSize);
    if (!pBuffer)
    {
        return XIBRT_SYSFATAL;
    }
    ulSize = fread(pBuffer, 1, ulSize, pFile);
    fclose(pFile);

    /* Copy the file contents into the result blob */
    xibrt_setBinary(hCtx, ulSize, pBuffer, hFileContents);

    /* Perform some cleanup and return success */
    free(pBuffer);
    return XIBRT_SUCCESS;
}

In the preceding code, parts that need to be changed or added are framed in orange. The function now raises an exception when it detects an abnormal situation. This might either interrupt the processing of the current document or abort the integration engine tasks.

You might reuse your LoadFile Custom Function in other projects. This is why you have it return absent when no file is found. In some projects, you can deal with this absent value; imagine that the contents of the file are simply copied in an optional node: no file means no occurrence of the node.

In the FoodBroker project, non-loading of the partner rates results in no processing at all. Therefore, you might want to reject messages as soon as you detect that the rates are not available to your system.

This detection is accomplished when the LoadFile Custom Function returns absent value. In this case you need to raise an exception that tells the integration engine to reject messages from the web server. But raising rejectMessage during the feeding of the rates is not appropriate. This must be done while processing data from your Mapping Flow input.

You face one difficulty here: the detection of unexpected behavior occurs in a different place than the one where you raise the alarm. You need to propagate your alarm silently using the absent value until you reach the appropriate exception trigger point.

To silently propagate the detected problem, you must be able to process the absent value in both the MB_tableLoader and MB_tableBuilder DML Blocks. In the former, the value returned by LoadFile is always placed in the output Business Document, even if that value is absent. In the later, instead of using the parse step, an empty output Business Document is generated using a dedicated Map.

Mapping Flow: order to partner with rates (1)

The MR_generateEmpty Map generates a Business Document that has only one occurrence of the node partner which groups both names and rate with an absent value.

Then, in the MB_extractorDML Block, the first step of the Decision-Path checks whether the document that comes from rates is full or not. If not, an exit step is triggered that raises the rejectMessage exception:

Mapping Flow: order to partner with rates (2)

The expression bound to the first if step in this Decision-Path is true whenever no occurrences of node partner exist in the input Business Document, or when at least one of the nodes name or rate is found with an absent value.

Related topics

FoodBroker project: Do the first steps

Create a Business Document for the customer request

Create a Business Document for the partner

Create a Business Document for partner rates

Build the Mapping Flow

FoodBroker project: Fill headers

FoodBroker project: Determine the incoming order ID

FoodBroker project: Generate the order ID

FoodBroker project: First steps in filling nodes

FoodBroker project: Extra charge for VISA payments

FoodBroker project: Introduction to data aggregation

FoodBroker project: Collect and copy parts

FoodBroker project: Manage rates

FoodBroker project: Handle absence of partner rates

Related Links