Thursday, August 2, 2012

Making an RFC call from a UDF in PI - For UKMS


You need to import the following in your java
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.helpers.DefaultHandler;

import com.kerry.pi.ukm.Customizing;
import com.kerry.pi.ukm.RFCAdapterException;
import com.sap.aii.af.service.api.Payload;
import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.lookup.Channel;
import com.sap.aii.mapping.lookup.LookupException;
import com.sap.aii.mapping.lookup.LookupService;
import com.sap.aii.mapping.lookup.RfcAccessor;

import com.sap.aii.mapping.lookup.XmlPayload;

import com.sap.aii.mappingtool.tf.rt.Container;
import com.sap.aii.mappingtool.tf.rt.GlobalContainer;
import com.sap.aii.mappingtool.tf.rt.ResultList;
import com.sap.basis.ukm.GetKeyMapping;
import com.sap.basis.ukm.Identifier;
import com.sap.basis.ukm.XmlHelper;
import com.sap.basis.ukm.datatypes.Mapping;

public class UKMSUDF {

public void rfcUKMS(String[] context, String[] srcScheme,
            String[] srcAgency, String[] srcValue, String[] tgtScheme,
            String[] tgtAgency, Channel channel, String[] alert, int OPTION,
            ResultList result, Container container)
            throws StreamTransformationException {

        AbstractTrace trace = container.getTrace();

        trace.addWarning("Stage:rfcUKMS:0");
        String NameChannel = "";
        String Party = "";
        String Service = "";

        if (OPTION == 1) {
            NameChannel = DEFAULT_CHANNEL1;
            Party = DEFAULT_PARTY1;
            Service = DEFAULT_SERVICE1;
        } else {
            NameChannel = DEFAULT_CHANNEL2;
            Party = DEFAULT_PARTY2;
            Service = DEFAULT_SERVICE2;

        }

        // Constants
        final String DELIM = " : ";
        // party1
        final String DEFAULT_PARTY = Party;
        final String DEFAULT_SERVICE = Service;
        final String DEFAULT_CHANNEL = NameChannel;
        final String SOURCE_SCHEME_VERSION_ID = "";
        final String SOURCE_SCHEME_AGENCY_SCHEME_ID = "";
        final String SOURCE_SCHEME_AGENCY_SCHEME_AGENCY_ID = "ZZZ";
        final String TARGET_SCHEME_VERSION_ID = "";
        final String TARGET_SCHEME_AGENCY_SCHEME_ID = "";
        final String TARGET_SCHEME_AGENCY_SCHEME_AGENCY_ID = "ZZZ";

        // Variables
        HashMap hm = new HashMap();
        HashMap hm2 = new HashMap();

        String[] keys = new String[srcValue.length];

        if (srcValue.length == 0)
            return;

        try {
            // Create GetKeyMapping
            GetKeyMapping keyMapping = new GetKeyMapping(trace, DEFAULT_PARTY,
                    DEFAULT_SERVICE, DEFAULT_CHANNEL);

            // Create identifiers, add mapping request and save key for every
            // source value
            for (int i = 0; i < srcValue.length; i++) {
                    if (OPTION==2 && srcValue[i].length() <= 5) srcValue[i] = srcValue[i].replace('*','x');

                // Create source and target identifiers
                Identifier sourceIdentifier = new Identifier(srcScheme[i],
                        SOURCE_SCHEME_VERSION_ID, srcAgency[i],
                        SOURCE_SCHEME_AGENCY_SCHEME_ID,
                        SOURCE_SCHEME_AGENCY_SCHEME_AGENCY_ID, srcValue[i]);
                Identifier targetIdentifier = new Identifier(tgtScheme[i],
                        TARGET_SCHEME_VERSION_ID, tgtAgency[i],
                        TARGET_SCHEME_AGENCY_SCHEME_ID,
                        TARGET_SCHEME_AGENCY_SCHEME_AGENCY_ID, "");

                // Add mapping request
                keyMapping.addMapping(context[i], sourceIdentifier,
                        targetIdentifier);

                // Create mapping key and put it into string array
                keys[i] = context[i] + DELIM + srcScheme[i] + DELIM
                        + srcAgency[i] + DELIM + srcValue[i] + DELIM
                        + tgtScheme[i] + DELIM + tgtAgency[i];

                // Trace mapping request
                trace.addWarning("Mapping request added for:" + keys[i]);

            } // End for

            // Trace request RFC XML
            trace.addWarning("Request RFC XML: "
                    + keyMapping.toRfcXml().toString());

            // Execute
            keyMapping.execute();

            // Retrieve results
            Iterator iter = keyMapping.getResultIterator();
            if (iter == null) {
                return;
            }



if (OPTION==2) {
           
            Node n = keyMapping.getResult();
            NodeList children = n.getChildNodes();
            if( children != null ) {
              for( int i = 0; i < children.getLength(); i++ ) {
                Node childNode = children.item( i );

                // here would be a good place to put your application logic
                // and do something base upon node type
               
                Node n1 = childNode;
                NodeList children1 = n1.getChildNodes();
                if( children1 != null ) {
                    String key = "";
                  for( int i1 = 0; i1 < children1.getLength(); i1++ ) {
                     
                    Node childNode1 = children1.item( i1 );

                    // here would be a good place to put your application logic
                    // and do something base upon node type
                    NodeList childNodes;
                    StringBuffer contents = new StringBuffer();
                   
                    childNodes =  childNode1.getChildNodes();
                    for(int i2=0; i2 < childNodes.getLength(); i2++ )
                    {
                      if( childNodes.item(i2).getNodeType() == Node.TEXT_NODE )
                      {
                    contents.append(childNodes.item(i2).getNodeValue());
                      }
                    }
                  
                    if (i1 % 2 == 0) { key = contents.toString(); }
                    else { key =  key.substring(key.indexOf(":")); hm2.put(key,contents.toString());  trace.addInfo( "adding hm2 => " + key + ":" + contents.toString() ); key ="";   }
                  }
                }
              }
            }
            }

            Mapping mappingResult;

            int countResult = 0;
            while (iter.hasNext()) {
                countResult++;
                mappingResult = (Mapping) iter.next();

                // Build key
                String myKey = mappingResult.getMainContextID() + DELIM
                        + mappingResult.getSource().getSchemeID() + DELIM
                        + mappingResult.getSource().getSchemeAgencyID() + DELIM
                        + mappingResult.getSource().getValue() + DELIM
                        + mappingResult.getTarget().getSchemeID() + DELIM
                        + mappingResult.getTarget().getSchemeAgencyID();

                // Put key and value into HashMap
                hm.put(myKey, mappingResult.getTarget().getValue());

            //    if (OPTION==2) { result.addValue((String) mappingResult.getTarget().getValue());  trace.addInfo((String) mappingResult.getTarget().getValue()); }
            }

            // Get values by associated keys and put them into ResultList

                   
            int iResult = 0;
           

            for (int i = 0; i < keys.length; i++) {
                    if (OPTION==2) { result.addValue((String) hm2.get((String) srcValue[i].substring(1))); trace.addInfo("returned"+srcValue[i].substring(1)); }

                trace.addInfo("Comparing result: " + srcValue.length + "-"
                        + countResult);
                // Throw an exception if keys[i] != countResult
                if (srcValue.length != countResult) {
                    throw new RuntimeException("Multiple Mappings for "
                            + keys[i]);
                }
                trace.addWarning("Key returned: " + hm.get(keys[i]));
                trace.addInfo("Alert: " + alert[i]);

                String returnValue = "";

                if (OPTION == 1) {
                    returnValue = (String) hm.get(keys[i]);

                    // throw an exception if the alert is set to Y and the
                    // source
                    // value is not blank and UKMS target value is blank
                    if (returnValue.length() == 0 && srcValue[i].length() > 0
                            && alert[i] != null && alert[i].compareTo("Y") == 0)
                        throw new RuntimeException(
                                "UKMS value Returned blank : " + keys[i]);
                    // Throw Exception if the return value is blank and the
                    // alert is
                    // set
                    trace.addWarning("Adding value to resultset");
                    result.addValue(returnValue);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Exception occurred: " + e.getMessage());
        }
    }// end method

    public void getUKMSValues(String[] ricef, String[] sourceSystem,
            String[] targetSystem, String[] fieldName, String[] qualf,
            String[] value, ResultList result, Channel channel,
            Container container) throws StreamTransformationException { // Retrieve
                                                                        // the
                                                                        // Context,
                                                                        // SrcScheme,SrcAgency,
                                                                        // TgtScheme,
                                                                        // TgtAgency,
                                                                        // Alert
        // Enable tracing



        AbstractTrace trace = container.getTrace();
    java.util.Date date= new java.util.Date();
        trace.addInfo((new Timestamp(date.getTime()).toString()));


        GlobalContainer globalContainer;
        Boolean isRecoverable = true;
        InputStream ist = null;
        Document document = null;
        Node rootNode = null;
        // Alert variables
        RfcAccessor RFCAccessor;
        final String FunctionModule = "Z_FM_MAP_GET_UKMS_CUST";

        final String FunctionModuleNamespace = "urn:sap-com:document:sap:rfc:functions";
        trace.addInfo (""+ricef.length+"-"+sourceSystem.length+"-"+targetSystem.length+""+fieldName.length+"-"+qualf.length+"-"+value.length);
       
       
       
        XmlPayload RFCResult;
        LookupException le;
        String[] context = new String[value.length];
        String[] srcScheme = new String[value.length];
        String[] srcAgency = new String[value.length];
        String[] tgtScheme = new String[value.length];
        String[] tgtAgency = new String[value.length];
        String[] hasAlert = new String[value.length];
        String[] qua = new String[value.length];
       
        if (qualf.length != value.length) {
            for (int g=0; g< value.length ; g++){
                qua[g]=qualf[0];
            }
           
        }else qua = qualf;
       
        globalContainer = container.getGlobalContainer();
        // Channel rfcChannel =
        // globalContainer.getInputParameters().getChannel("rfc_channel");

        RFCAccessor = LookupService.getRfcAccessor(channel);
        NodeList ctCustomizingNodes ;

      try {

        //for (int i = 0; i < value.length; i++) {

            trace.addInfo("Loop Starts here: " + value.length);
            StringBuffer tmpStr = new StringBuffer();
            tmpStr.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><ns0:");
            tmpStr.append(FunctionModule);
            tmpStr.append(" xmlns:ns0=\"");
            tmpStr.append(FunctionModuleNamespace);
            tmpStr.append("\">");
            tmpStr.append("<RICEFW>");
            tmpStr.append(ricef[0]);
            tmpStr.append("</RICEFW>");
            tmpStr.append("<SOURCE>");
            tmpStr.append(sourceSystem[0]);
            tmpStr.append("</SOURCE>");
            tmpStr.append("<TARGET>");
            tmpStr.append(targetSystem[0]);
            tmpStr.append("</TARGET>");
            tmpStr.append("<FIELD>");
            tmpStr.append(fieldName[0]);
            tmpStr.append("</FIELD>");
            tmpStr.append("</ns0:");
            tmpStr.append(FunctionModule);
            tmpStr.append(">");
            String FunctionModuleXML = tmpStr.toString();
           
//            String FunctionModuleXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ns0:"
//                    + FunctionModule
//                    + " xmlns:ns0=\""
//                    + FunctionModuleNamespace
//                    + "\">"
//                    + "<RICEFW>"
//                    + ricef[0]
//                    + "</RICEFW>"
//                    + "<SOURCE>"
//                    + sourceSystem[0]
//                    + "</SOURCE>"
//                    + "<TARGET>" + targetSystem[0] + "</TARGET>"
//                    // + "<QUALF>"
//                    // + qualf[i]
//                    // + "</QUALF>"
//                    + "<FIELD>" + fieldName[0] + "</FIELD>" + "";
//
//            FunctionModuleXML = FunctionModuleXML + "" + "</ns0:"
//                    + FunctionModule + ">";

           

                trace.addWarning("RFC call1 " + FunctionModuleXML);
                // Create an XML input stream that represents the RFC request
                // message.
                InputStream is = new ByteArrayInputStream(
                        FunctionModuleXML.getBytes());

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

                // Execute the lookup.
                // if (i > 0)
                RFCResult = RFCAccessor.call(payload);

            trace.addWarning("Call made to retrieve customizing");
            // PARSE THE RETURN xml
            //try {
                DocumentBuilderFactory factory = DocumentBuilderFactory
                        .newInstance();
                if (factory == null) {
                    throw new Exception(
                            "DocumentBuilderFactory factory is null");
                }

                DocumentBuilder builder = factory.newDocumentBuilder();
                if (builder == null) {
                    throw new Exception("DocumentBuilder builder is null");
                }

                document = builder.parse(RFCResult.getContent());
                if (document == null) {
                    trace.addInfo("Document is null");
                    throw new Exception("Document document is null");
                }

            // Customizing retrieved into XML and parsed into document and
            // nodelist

           

           
         //} // end for loop
        Element docEle = document.getDocumentElement();
        ctCustomizingNodes = docEle.getElementsByTagName("item");
        // This should only have 1 customizing returned.
        for (int i = 0; i < value.length; i++) {
            // RETURN an error if customizing has more than 1 entry
            trace.addWarning("Customizing returned : "
                    + ctCustomizingNodes.getLength());
            for (int k = 0; k < ctCustomizingNodes.getLength(); k++) {
                String cont = "";
                String sa = "";
                String ss = "";
                String ta = "";
                String ts = "";
                String alert = "";
                String qual="";
               
                NodeList nl = ctCustomizingNodes.item(k).getChildNodes();
                for (int j = 0; j < nl.getLength(); j++) {
                   
                    Node node = nl.item(j);
                          if (node.getNodeName().compareTo("QUALIFIER") == 0) {
                          qual = node.getFirstChild().getNodeValue();
                            trace.addInfo("QUALIFIER" + qual);
                        }
                        if (node.getNodeName().compareTo("CONTEXT") == 0) {
                            cont = node.getFirstChild().getNodeValue();
                            trace.addInfo("CONTEXT" + cont);
                        }
                        if (node.getNodeName().compareTo("SOURCE_AGENCY") == 0) {
                            sa = node.getFirstChild().getNodeValue();
                            trace.addInfo("SOURCE_AGENCY" + sa);
                        }

                        if (node.getNodeName().compareTo("SOURCE_SCHEME") == 0) {
                            ss = node.getFirstChild().getNodeValue();
                            trace.addInfo("SOURCE_SCHEME" + ss);
                        }
                        if (node.getNodeName().compareTo("TARGET_AGENCY") == 0) {
                            ta = node.getFirstChild().getNodeValue();
                            trace.addInfo("TARGET_AGENCY" + ta);
                        }
                        if (node.getNodeName().compareTo("TARGET_SCHEME") == 0) {
                            ts = node.getFirstChild().getNodeValue();
                            trace.addInfo("TARGET_SCHEME" + ts);
                        }
                        if (node.getNodeName().compareTo("ALERT") == 0) {
                            alert = node.getFirstChild().getNodeValue();
                            trace.addInfo("ALERT" + alert);
                        }
                   
            } // end J
                trace.addInfo("each qualifier:" +qua[i]);
                if (qual.compareTo(qua[i])==0) {
                    trace.addInfo("Found qualifer " + qual);
                    context[i] = cont;
                    srcAgency[i] = sa;
                    srcScheme[i] = ss;
                    tgtAgency[i] = ta;
                    tgtScheme[i] = ts;
                    hasAlert[i] = alert;
                   
                   
                }
        } // end K

        }// end i
       
          } catch (Throwable t) {
                trace.addWarning("Exception " + t.getMessage());
        }
        // Make rfc call to retrieve UKMS.
        trace.addInfo(channel.toString());
    trace.addWarning(channel.toString());
        trace.addInfo((new Timestamp(date.getTime()).toString()));
        rfcUKMS(context, srcScheme, srcAgency, value, tgtScheme, tgtAgency,
                channel, hasAlert, 1, result, container);
        trace.addInfo((new Timestamp(date.getTime()).toString()));

    } // end method

}

SAP PI - Dynamic File Name generation



In some cases the requirements of the file being dropped by PI requires to be certain specific formats. For e.g. Date or sequence numbers required. Even though there is a date stamp privided by the File adapter, it is not very flexible in terms of format. Thus the below method is quite helpful. Everything happens in the message mapping.

There is one config required in the File Receiver in the Integration Directory:




The next thing to configure is the message mapping in the ESR, create a UDF in the message mapping as follows:


The reason why I am imported the Seeburger functions are because in this particular case, the file name required a sequence number which increments for each customer. Thus it creates a seeburger variable and gets the next sequence number. Also this UDF should be called once only in the mapping. It should basically have the following code to make the file name be as per what you define:

 DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","FileName");

SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd");
String timestamp = dateformat.format(new Date());

String filename1= "OTI_I_18_"+customerGLN + "_" + customerNumber +"_" +".txt";

conf.put(key, filename1);

The above should do the trick for a special date formatted file name.