Skip to Content
0

SAP PO 7.5: Java class cast exception after RFC lookup

Dec 01, 2017 at 08:10 AM

138

avatar image

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)
10 |10000 characters needed characters left characters exceeded
* Please Login or Register to Answer, Follow or Comment.

5 Answers

Muniyappan Marasamy Dec 04, 2017 at 07:41 AM
1

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

Share
10 |10000 characters needed characters left characters exceeded
Muniyappan Marasamy Dec 04, 2017 at 09:54 AM
1

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?

Share
10 |10000 characters needed characters left characters exceeded
Peter Wallner Mar 23 at 10:15 AM
1

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

Show 1 Share
10 |10000 characters needed characters left characters exceeded

Thank you Peter for posting the solution.

0
Peter Wallner Dec 04, 2017 at 08:32 AM
0

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;
        }
    }
}

Share
10 |10000 characters needed characters left characters exceeded
Peter Wallner Dec 04, 2017 at 10:32 AM
0

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

Show 5 Share
10 |10000 characters needed characters left characters exceeded

can you un check "XML Toolkit" and execute the mapping and see if it works?

0

Dear Muni M,

No, it does not work. If I remove the tick for "XML Toolkit" and execute the mapping in ESR I get this:

Transformer Configuration Exception occurred when loading XSLT edifact.d97a.orders.rfcLookup.CountryOfOrigin.xsl; details: Cannot convert data-type 'reference' to 'java.util.Map'.
See error logs for details

Best regards, Peter

0

in the java code, you can put one more trace after this line.

trace.addDebugMessage("RFC Response: " + tee.getStringContent());
                responseNode = document.getFirstChild();
trace.addDebugMessage("after resonsenode retrieved");

can you confirm if you are able to get "after resonsenode retrieved" in the ESR testing.

Also add debug message in the catch section." Add trace.addDebugMessage("in the exception catch blog");"

catch (Throwable t) {
              StringWriter sw = new StringWriter();
              t.printStackTrace(new PrintWriter(sw));
              trace.addWarning(sw.toString());
              trace.addDebugMessage("in the exception catch blog");
          }

Also please check if you are getting "in the exception catch blog" in the trace log when you test from ESR.

Regards,

Muni

0

Hello Muni M.

I added these lines to the Java code and tested in ESR and end-to-end with XPI Inspector.

1) with XML Toolkit flag:
ESR:
I see my request and response and also "after responsenode retrieved":

I see the same in XPI Inspector. I do not see "in the exception catch blog" anywhere.

But I still see these errors in XPI Inspector:

Cannot cast class com.sun.org.apache.xerces.internal.dom.DeferredCommentImpl to interface org.w3c.dom.Element
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
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

To me this looks like that the IDOC AAE Adapter can't cope with the Node ResponseNode.

2) without XML Toolkit flag

I also tried with out the XML Toolkit flag and therefore I also changed the XSLT a little and I do a cast on the $inputparam in the XSLT:

<xsl:variable name="response"
            select="lookup:execute($request, $ReceiverService, $rfcChannel, xsltc:cast('java.util.Map',$inputparam))"/>

but then I receive this error:

com.sap.aii.adapter.rfc.core.client.RfcClientException: could not get functionname from XML requst: com.sap.aii.adapter.rfc.RfcAdapterException: failed to read funtionname from XML document: missing namespace declaration(2)'

This is difficult to debug. Do you have any ideas? Otherwise I will open an OSS ticket.

Thank you again for your help and best regards,
Peter

uqrpz.png (17.5 kB)
0

Hi Peter,

Thank you for updating. Please open OSS ticket. I will update you if i find anything.

Regards,

Muni

1