Skip to Content

SAP PO 7.5: Java class cast exception after RFC lookup

Dear experts,

We are moving from PI 7.30 to PO 7.50

We are using a Java map which does an RFC lookup. We call that from an XSLT map.
We are using the code from this thread posted by Till Dreier:
https://archive.sap.com/discussions/thread/1811977
which is working fine on PI 7.30.

But now on PO 7.50 we have an issue:
when we do an end-to-end test I can see the RFC request and the RFC response payload
in XPI Inspector:

So the lookup itself is working.

But then I get these warnings and errors in XPI Inspector:


No Information Available for Audit Key : Adding control record to payload failed due to Error while adding control record to idoc payload due to Cannot cast class com.sun.org.apache.xerces.internal.dom.DeferredCommentImpl to interface org.w3c.dom.Element

Cannot cast class com.sun.org.apache.xerces.internal.dom.DeferredCommentImpl to interface org.w3c.dom.Element

com.sap.aii.af.idoc.exception.IDOCAdapterException: Error while adding control record to idoc payload due to Cannot cast class com.sun.org.apache.xerces.internal.dom.DeferredCommentImpl to interface org.w3c.dom.Element


Does anyone have an idea on this?

Thank you and best regards,
Peter

request.png (6.0 kB)
response.png (5.3 kB)
warning.png (6.6 kB)
error.png (21.7 kB)
Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

5 Answers

  • Dec 04, 2017 at 07:41 AM

    looks issue with casting, can you share you java and xslt code here?

    hope, you have taken care casting in the xslt as per your previous questions

    https://answers.sap.com/questions/336309/po-75-xsl-map-with-java-functions.html

    Add comment
    10|10000 characters needed characters exceeded

  • Dec 04, 2017 at 09:54 AM

    Thank you for your response.

    Before you do the changes, you can do the mapping test in ESR? is it failing there?

    or are you able to see the output and it fails in idoc adapter bean?

    Add comment
    10|10000 characters needed characters exceeded

  • Mar 23 at 10:15 AM

    Hello Muni,

    Sorry my late reply. But I think it is worth to read for anyone who is using the RfcLookup.java code on SAP PO.
    Originally the code was written by Thorsten Nordholm Søbirk. It was adapted by Till Dreier shown in this thread:
    https://archive.sap.com/discussions/thread/1811977

    1) first of all "XML Toolkit" must be ticked on SAP PO 7.5 - this was also confirmed by SAP in my OSS ticket.
    2) there is a line in the java code which does not work on our PO 7.5 system anymore:
    The affected line is this one:

    responseNode = document.getFirstChild();

    The responseNode is empty on the PO system after this line.

    We changed the coding to this now:

    NodeList nodeList = document.getElementsByTagName("*");
    responseNode = RfcLookup.getNode(document.getDocumentElement().getNodeName(),nodeList);
    
    Method getNode looks like this:
    static Node getNode(String tagName, NodeList nodes) {
      for ( int x = 0; x < nodes.getLength(); x++ ) {
      Node node = nodes.item(x);
      if (node.getNodeName().equalsIgnoreCase(tagName)) {
      return node;
      }
      }
    
      return null;
      }

    The "responseNode" is now filled with the RFC response structure (single element or even an internal table returned by the lookup).

    Best regards, Peter

    Add comment
    10|10000 characters needed characters exceeded

  • Dec 04, 2017 at 08:32 AM

    Hello Muni M,

    Thank you. In our operation mapping we still have "XML Toolkit" ticked.
    If we use the casting we can untick that as far as I understand.

    In our XSLT we are not casting yet.
    Would we have to cast $request and $response?

    Thank you for having a look at this and best regards,
    Peter

    We are using the following XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet extension-element-prefixes="lookup xd"
        xmlns:lookup="com.xxxxx.global.RfcLookup"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
        exclude-result-prefixes="xd">
        <xsl:output encoding="UTF-8" method="xml" indent="yes"/>
    
    
        <!-- SAP XI Queue Parameters -->
        <xsl:param name="ReceiverService"/>
        <xsl:param name="inputparam"/>
    
        <xsl:variable name="rfcChannel" select="'CC_RFC_ADAPTER_IN'"/>
    
    
        <xsl:template match="C_C212_2/D_7140">
            <xsl:variable name="SupplierArticle" select="."/>
    
            <xsl:element name="{local-name(.)}">
                <xsl:value-of select="$SupplierArticle"/>
            </xsl:element>
    
            <xsl:call-template name="rfcLookup">
                <xsl:with-param name="request">
                    <rfc:Z_XI_COUNTRY_OF_ORIGIN_GET
                        xmlns:rfc="urn:sap-com:document:sap:rfc:functions">
                        <ID_SUPPLIER_ARTICLE>
                            <xsl:value-of select="string($SupplierArticle)"/>
                        </ID_SUPPLIER_ARTICLE>
                    </rfc:Z_XI_COUNTRY_OF_ORIGIN_GET>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:template>
    
        <!--select="lookup:execute($request, $ReceiverService, $rfcChannel, $inputparam)"/>-->
        <xsl:template name="rfcLookup">
            <xsl:param name="request"/>
    
            <xsl:variable name="response"
                select="lookup:execute($request, $ReceiverService, $rfcChannel, $inputparam)"/>
            <!--<xsl:variable name="response" select="lookup:execute($request, 'BS_T_CH_ERP', $rfcChannel, $inputparam)"/>-->
    
            <xsl:comment>ED_COUNTRYORI <xsl:value-of select="$response/ED_COUNTRYORI"/>  // </xsl:comment>
            <xsl:comment>ED_COUNTRYORI2 <xsl:value-of select="$response"/>  // </xsl:comment>
            
            <xsl:element name="CountryOfOrigin">
                <!--<xsl:value-of select="$response/rfc:ED_COUNTRYORI"/>-->
                <xsl:value-of select="$response//ED_COUNTRYORI"/>
            </xsl:element> 
     
        </xsl:template>
    
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    

    And this is the java code:

    package pi_mappings;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    import java.util.Map;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.Source;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
     
    
    import com.sap.aii.mapping.lookup.Channel;
    import com.sap.aii.mapping.api.StreamTransformationConstants;
    import com.sap.aii.mapping.api.AbstractTrace;
    import com.sap.aii.mapping.lookup.RfcAccessor;
    import com.sap.aii.mapping.lookup.LookupService;
    import com.sap.aii.mapping.lookup.XmlPayload;
    
    
    /**
    * @author Thorsten Nordholm Søbirk, AppliCon A/S
    *
    * Helper class for using the XI Lookup API with XSLT mappings for calling RFCs.
    * The class is generic in that it can be used to call any remote-enabled
    * function module in R/3. Generation of the XML request document and parsing of
    * the XML response is left to the stylesheet, where this can be done in a very
    * natural manner.
    *
    * Note:
    * Changed the class that request is sent as String, because of IndexOutOfBound-exception
    * When sending multiple requests in one XSLT mapping.
    *
    */
    public class RfcLookup {
        /**
        * Execute RFC lookup.
        * @param request RFC request - Note: changed to String
        * @param service name of service
        * @param channelName name of communication channel
        * @param inputParam mapping parameters
        * @return Node containing RFC response
        */
        public static Node execute( String request,
                String service,
                String channelName,
                Map inputParam)
    
        {
              AbstractTrace trace = (AbstractTrace) inputParam.get(StreamTransformationConstants.MAPPING_TRACE);
              Node responseNode = null;
    
    
              try {
                  // Get channel and accessor
                  Channel channel = LookupService.getChannel(service, channelName);
                  RfcAccessor accessor = LookupService.getRfcAccessor(channel);
    
     
    
                  // Serialise request NodeList - Note: Not needed anymore as request is String
                  /*TransformerFactory factory = TransformerFactory.newInstance();
                  Transformer transformer = factory.newTransformer();
    
                  Source source = new DOMSource(request.item(0));
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
                  StreamResult streamResult = new StreamResult(baos);
                  transformer.transform(source, streamResult);*/
    
     
    
                    // Note: Add xml header and remove linefeeds for the request string
                    request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+request.replaceAll("[\r\n]+", ""); 
     
                    // Note: Get byte Array from request String to send afterwards
                    byte[] requestBytes = request.getBytes();
     
                  // Note: Not used anymore as request is String
                    //byte[] requestBytes = baos.toByteArray();
    
     
    
                    trace.addDebugMessage("RFC Request: " + new String(requestBytes));
    
                    // Create input stream representing the function module request message
                    InputStream inputStream = new ByteArrayInputStream(requestBytes);
    
                 
    
                    // Create XmlPayload
                    XmlPayload requestPayload =LookupService.getXmlPayload(inputStream);
    
     
    
                    // Execute lookup
                    XmlPayload responsePayload = accessor.call(requestPayload);
                    InputStream responseStream = responsePayload.getContent();
                    TeeInputStream tee = new TeeInputStream(responseStream);
    
     
    
                    // Create DOM tree for response
                    DocumentBuilder docBuilder =DocumentBuilderFactory.newInstance().newDocumentBuilder();
                    Document document = docBuilder.parse(tee);
                    trace.addDebugMessage("RFC Response: " + tee.getStringContent());
                    responseNode = document.getFirstChild();
    
              } catch (Throwable t) {
                  StringWriter sw = new StringWriter();
                  t.printStackTrace(new PrintWriter(sw));
                  trace.addWarning(sw.toString());
              }
              return responseNode;
    
        }
        /**
        * Helper class which collects stream input while reading.
        */
        static class TeeInputStream extends InputStream {
              private ByteArrayOutputStream baos;
              private InputStream wrappedInputStream;
    
              TeeInputStream(InputStream inputStream) {
                    baos = new ByteArrayOutputStream();
                    wrappedInputStream = inputStream;
              }
              /**
              * @return stream content as String
              */
    
              String getStringContent() {
                    return baos.toString();
    
              }
              /* (non-Javadoc)
              * @see java.io.InputStream#read()
              */
              public int read() throws IOException {
                  int r = wrappedInputStream.read();
                  baos.write(r);
                  return r;
            }
        }
    }
    
    
    Add comment
    10|10000 characters needed characters exceeded

  • Dec 04, 2017 at 10:32 AM

    Dear Muni M,

    When I test the mapping in ESR it is not failing. I have 2 steps in the operation mapping.
    I see the RFC Response in the log of the RFC mapping step.
    When I test both steps - RFC and main mapping - still no error but the RFC response value is not considered in the main map.

    In XPI Inspector I also see my RFC response (log entry) but then I get errors (screenshots in my first post).

    It seems to me the error happens when my RFC response is parsed to XML and handed to the next mapping step.
    And as a result also an IDOCAdapterException occurs.

    Thank you again, Peter

    Add comment
    10|10000 characters needed characters exceeded