Skip to Content

Hi all, in this blog i will show, how to use UDF to caching values in hashmap in GlobalContainer.

Logic of UDF is simple.

1. We check existence of hashmap in GlobalContainer. Hashmap should have unique name for rfc-lookup. It can be output node name of rfc-lookup function.

2. If we have no hashmap in GlobalContainer, then we create it (hashmap), put to hashmap value from rfc-lookup and push hashmap to GlobalContainer.

3. If we have hashmap then we check value.

3.1 If we have no value, then we put to hashmap value from rfc-lookup and update hashmap in GlobalContainer.

3.2 If we have value, then we return it and exit udf.

And that’s all.

See code below:


@LibraryMethod(title="RFC_CALL_HASH", description="", category="FL_local", type=ExecutionType.SINGLE_VALUE)
    public String RFC_CALL_HASH (
        @Argument(title="")  String input_node_value,
        @Argument(title="Service")  String Service,
        @Argument(title="Channel")  String Channel,
        @Argument(title="Function Module")  String FM,
        @Argument(title="Input Node")  String Input_Node_name,
        @Argument(title="Output Node")  String Output_Node_name,
         Container container)  throws StreamTransformationException{
            AbstractTrace trace = container.getTrace();
        // Set default values
            boolean put_to_cache = false;
        final String SERVICE = Service, // Name of service defined in XI configuration
        CHANNEL_NAME = Channel, // Name of communication channel defined for service
        SAP_RFC_NAMESPACE = "urn:sap-com:document:sap:rfc:functions", // Namespace for SAP RFC definitions
        FUNCTION_MODULE = FM, // Name of the function module called
        VALUE_NOT_FOUND = "NOT FOUND"; // Default return value in case something goes wrong
    
        if (input_node_value.equals("")) return ""; // if input value is empty just return empty string and exit from udf
    
    
        GlobalContainer globalContainer;
        HashMap<String, String> cache;
    
        globalContainer = container.getGlobalContainer();
        // check hash existence.
        if (globalContainer.getParameter(Input_Node_name)!=null )
        {
            // get object (hashmap) from GlobalContainer       
            cache = (HashMap<String, String>)globalContainer.getParameter(Input_Node_name);
            // get Value from hashmap
            String retval = cache.get(input_node_value);
            // if value not null - return it,
            // if value is null, then put_to_cache set true
            if (retval == null)
            {
                put_to_cache=true;
            }
            else
            {
                return retval; // exit from udf with value from hash
            }
        
        }
        else
        {
            // create new hashmap if we have no it yet and set put_to_cache in true
            cache = new HashMap<String, String>();
            put_to_cache=true;
        
        
        
        }
  
    // this part will run if we have no hashmap or have no our value in our hashmap
    // start to call RFC. This part is copied from open source code project.
        // Create document busilder 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 +
            "\"><"+Input_Node_name+">"+input_node_value+"</"+Input_Node_name+"></ns0:" +
        FUNCTION_MODULE + ">";
    // Prepare and perform RFC Lookup ...
    RfcAccessor accessor = null;
    Payload result = null;
 
 
    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.
// this part depends on your xml structure!        ------------- //
   
       poItems = docResponse.getElementsByTagName(
                Output_Node_name);
       //returnValue+=poItems.getLength();
        if (poItems.getLength()>0)
                 if (poItems.item(0).getChildNodes().getLength()>0)
            returnValue = poItems.item(0).getChildNodes().item(0).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);
}
// end of calling RFC
// return the result obtained above
// now if we have put_to_cache == true, then we add it to our hashmap
if (put_to_cache==true)
{    cache.put(input_node_value, returnValue);
     globalContainer.setParameter(Input_Node_name, cache); // update or set our hashmap in GlobalContainer
    }
    // and return value from rfc-lookup
return returnValue;
    }
}



return returnValue;
    }
}


Here i coded RFC-lookup in Java, but you can use standart RFC-lookup in message mapping, but logic will be little different.

Have fun 🙂

To report this post you need to login first.

3 Comments

You must be Logged on to comment or reply to a post.

  1. Amit Kamat

    Hi,

    I went trhu your blog. I am doing a RFC look up to send multiple values as input and get multiple results in a single call. I am able to achieve that correctly. Now I need to store the array of values returned in PI. Can you please tell me if I can do this using the above method and what changes would be needed. I am using graphical look up.

    (0) 

Leave a Reply