Registration

Dear SAP Community Member,
In order to fully benefit from what the SAP Community has to offer, please register at:
http://scn.sap.com
Thank you,
The SAP Community team.
Skip to end of metadata
Go to start of metadata

Summary

This post describes a user-defined mapping function for SAP XI that performs an RFC lookup using the SAP Mapping Lookup library in a scenario involving purchase orders.

This code builds on previously posted code examples on SDN, including an article by Danny De Roovere (http://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/70d90a91-3cf4-2a10-d189-bfd37d9c3231).

The code presented here relates specifically to a purchase order scenario involving the BAPI_PO_GETITEMS function module. The purpose of the lookup is to retrieve the value of an attribute of a specific order item (e.g., PRICE_UNIT), given the ID of the order (PURCHASEORDER) and the ID of the order item (PO_ITEM).

Besides serving as a reference for using the a RFC lookup using the SAP Mapping Lookup library, this example also provides some insights into how to parse the retrieved XML document for the desired information.

Function Signature

Inputs:             id of document containing list (e.g., PO Number), list item id value (PO item number)

Output:            value of list item attribute (e.g., PRICE_UNIT)

Implementation

Below are the key steps for implementing this lookup function in a mapping

  1. Create the mapping
  2. Create new user-defined function (UDF) in mapping
  3. Provide input parameter information for the UDF
  4. Provide the libraries used in the code
  5. Paste the code
  6. Adjust the code so it runs in your environment and serves your purpose. This includes at least providing changing the SERVICE and CHANNEL_NAME. In addition a different result attribute (in our case PRICE_UNIT) or even an entirely different FUNCTION_MODULE may be specified. The latter may require further adjustments to the rfcXML string!
  7. Test the mapping

Code 


/******************************
*  Purpose: RFC Lookup of document containing list (e.g., Purchase Order), returning value of list item with matching item id
*  Inputs: 1 - id document containing list (e.g., PO Number), 2 - list item id value (PO item number)
*  Output: value of list item (e.g., PRICE_UNIT)
*
*  Authors: Marc Haines, Innograte LLC & Kyle Fortney
*  created September, 2008
*  adapted from How to Lookup Data Via a RFC User Defined Function? - Thanks Danny De Roovere !
*  see https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/70d90a91-3cf4-2a10-d189-bfd37d9c3231
*******************************/

/* Define the following input parameters
   PO_Number (String)
   Item_Number (String)
*/

/* Provide the following imports:
   com.sap.aii.mapping.lookup.*;java.util.Iterator;java.util.Map;java.io.*;javax.xml.parsers.*;org.w3c.dom.*;
*/

// Enable tracing
AbstractTrace trace = container.getTrace();

// Set default values
final String SERVICE = "MY_SAP_SYSTEM", // Name of service defined in XI configuration
CHANNEL_NAME = "cc_rfc_receiver", // Name of communication channel defined for service
SAP_RFC_NAMESPACE = "urn:sap-com:document:sap:rfc:functions", // Namespace for SAP RFC definitions
FUNCTION_MODULE = "BAPI_PO_GETITEMS", // Name of the function module called
LIST_CONTENT_TAG = "PO_ITEMS", // Element that conatains the list items (e.g., PO_ITEMS contains multiple item elements)
LIST_ITEM_ID_TAG = "PO_ITEM", // Element of individual list item that contains the id of the item
LIST_VALUE_TAG = "PRICE_UNIT", // Element of the individual list item that conatains the value desired for output
VALUE_NOT_FOUND = ""; // Default return value in case something goes wrong

// Create document builder to create DOM XML document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
factory.setNamespaceAware(false);
factory.setValidating(false);

try {
        // Create XML document using document builder
        builder = factory.newDocumentBuilder();
} catch (Exception e) {
        trace.addWarning("Error creating DocumentBuilder - " +
                e.getMessage());
        return null;
}


// Define XML for RFC Request
String rfcXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ns0:" +
        FUNCTION_MODULE + " xmlns:ns0=\"" + SAP_RFC_NAMESPACE +
        "\"><ACCTASSCAT/><CREATED_BY/><DELETED_ITEMS/><DOC_DATE/><DOC_TYPE/><ITEMS_OPEN_FOR_RECEIPT/><ITEM_CAT/><MATERIAL/><MATERIAL_EVG><MATERIAL_EXT/><MATERIAL_VERS/><MATERIAL_GUID/></MATERIAL_EVG><MAT_GRP/><PLANT/><PREQ_NAME/><PURCHASEORDER>" +
        PO_Number + "</PURCHASEORDER><PURCH_ORG/><PUR_GROUP/><PUR_MAT/><PUR_MAT_EVG><MATERIAL_EXT/><MATERIAL_VERS/><MATERIAL_GUID/></PUR_MAT_EVG><SHORT_TEXT/><SUPPL_PLANT/><TRACKINGNO/><VENDOR/><WITH_PO_HEADERS/><PO_HEADERS><item><PO_NUMBER/><CO_CODE/><DOC_CAT/><DOC_TYPE/><CNTRL_IND/><DELETE_IND/><STATUS/><CREATED_ON/><CREATED_BY/><ITEM_INTVL/><LAST_ITEM/><VENDOR/><LANGUAGE/><PMNTTRMS/><DSCNT1_TO/><DSCNT2_TO/><DSCNT3_TO/><CASH_DISC1/><CASH_DISC2/><PURCH_ORG/><PUR_GROUP/><CURRENCY/><EXCH_RATE/><EX_RATE_FX/><DOC_DATE/><VPER_START/><VPER_END/><APPLIC_BY/><QUOT_DEAD/><BINDG_PER/><WARRANTY/><BIDINV_NO/><QUOTATION/><QUOT_DATE/><REF_1/><SALES_PERS/><TELEPHONE/><SUPPL_VEND/><CUSTOMER/><AGREEMENT/><REJ_REASON/><COMPL_DLV/><GR_MESSAGE/><SUPPL_PLNT/><RCVG_VEND/><INCOTERMS1/><INCOTERMS2/><TARGET_VAL/><COLL_NO/><DOC_COND/><PROCEDURE/><UPDATE_GRP/><DIFF_INV/><EXPORT_NO/><OUR_REF/><LOGSYSTEM/><SUBITEMINT/><MAST_COND/><REL_GROUP/><REL_STRAT/><REL_IND/><REL_STATUS/><SUBJ_TO_R/><TAXR_CNTRY/><SCHED_IND/><VEND_NAME/><CURRENCY_ISO/><EXCH_RATE_CM/><HOLD/></item></PO_HEADERS><PO_ITEMS><item><PO_NUMBER/><PO_ITEM/><ADDRESS/><MATERIAL/><PUR_MAT/><INFO_REC/><ITEM_CAT/><ACCTASSCAT/><AGREEMENT/><AGMT_ITEM/><STORE_LOC/><MAT_GRP/><SHORT_TEXT/><DISTRIB/><PART_INV/><KANBAN_IND/><PLANT/><ALLOC_TBL/><AT_ITEM/><UNIT/><NET_PRICE/><PRICE_UNIT/><CONV_NUM1/><CONV_DEN1/><ORDERPR_UN/><PCKG_NO/><PROMOTION/><ACKN_REQD/><TRACKINGNO/><PLAN_DEL/><RET_ITEM/><AT_RELEV/><VEND_MAT/><MANUF_PROF/><MANU_MAT/><MFR_NO/><MFR_NO_EXT/><PO_PRICE/><SHIPPING/><ITEM_CAT_EXT/><PO_UNIT_ISO/><ORDERPR_UN_ISO/><PREQ_NAME/><DISP_QUAN/><QUAL_INSP/><NO_MORE_GR/><DELETE_IND/><NO_ROUNDING/><TAX_CODE/><MATERIAL_EXTERNAL/><MATERIAL_GUID/><MATERIAL_VERSION/><PUR_MAT_EXTERNAL/><PUR_MAT_GUID/><PUR_MAT_VERSION/><VAL_TYPE/><PR_CLOSED/><ACKNOWL_NO/></item></PO_ITEMS><RETURN><item><TYPE/><CODE/><MESSAGE/><LOG_NO/><LOG_MSG_NO/><MESSAGE_V1/><MESSAGE_V2/><MESSAGE_V3/><MESSAGE_V4/></item></RETURN></ns0:" +
        FUNCTION_MODULE + ">";

// Prepare and perform RFC Lookup ...
RfcAccessor accessor;
Payload result;


try {
        //  Determine a communication channel (Business system + Communication channel)
        Channel channel = LookupService.getChannel(SERVICE, CHANNEL_NAME);

        //  Get a RFC accessor for the channel.
        accessor = LookupService.getRfcAccessor(channel);

        //  Create an XML input stream that represents the RFC request message.
        InputStream is = new ByteArrayInputStream(rfcXML.getBytes());

        //  Create the XML Payload
        XmlPayload payload = LookupService.getXmlPayload(is);

        //  Execute the lookup.
        result = accessor.call(payload);

        if (result == null) {
                trace.addWarning("result of RFC call is null");
        }

} catch (LookupException e) {
        trace.addWarning("Error during lookup - " + e);
}

// Parsing RFC Response Document
Document docResponse = null;
InputStream in = result.getContent();
String returnValue = VALUE_NOT_FOUND;
NodeList poItems = null;

try {
        docResponse = builder.parse(in);
        if (docResponse == null) {
                trace.addWarning("docResponse is null");
        }
        // Get the list of PO items from RFC structure (item nodes, child nodes of PO_ITEMS)
        // Important: getElementsByTagName returns a *node list*.
        //            So the first - even if there is only one - item needs to be picked - item(0)!
        //            Only when having the PO_ITEMS *node* the getChildNodes() function can be used to get the PO items.
        poItems = docResponse.getElementsByTagName(
                LIST_CONTENT_TAG).item(0).getChildNodes();

        // Iterate over PO items (item nodes in RFC structure) until item with right item number is found
        for (int i = 0; i < poItems.getLength(); i++) {
                Element e = (Element) poItems.item(i);
                // Get the PO_ITEM value for the current item
                String poItem =
                        e.getElementsByTagName(LIST_ITEM_ID_TAG).item(0).getFirstChild().getNodeValue();

                // Test if value of PO_ITEM from current node matches input parameter Item_Number
                if (poItem.equals(Item_Number)) {
                        // Assign text value PRICE_UNITof desired tag to result
                        returnValue = e.getElementsByTagName(LIST_VALUE_TAG).item(
                                0).getFirstChild().getNodeValue();
                }
        }
}
catch (Exception e) {
        trace.addWarning("Error when parsing RFC Response - " + e.getMessage());
}

try {

        // Free resources, close the accessor..
        if (accessor != null) {
                try {
                        accessor.close();
                } catch (LookupException e) {
                        trace.addWarning( "Error while closing accessor " + e.getMessage());
                }
        }
} catch (Exception e) {
        trace.addWarning("Result value not found in DOM - " + e);
}

// return the result obtained above
return returnValue;