cancel
Showing results for 
Search instead for 
Did you mean: 

XSLT and Java lookup cache

Former Member
0 Kudos

Hi,

I´m trying the "Easy RFC lookup from XSLT mappings using a Java helper class" article and I getting a weird problem.

The result of the RFC lookup called inside the java class is maintained in a kind of cache and I always get the same results independent of the parameters I use in the following calls.

Just after calling a Complete Cache Refresh (SXI_CACHE) I got a new result to the lookup.

If I call in the Interface Mapping Test option it runs fine. However, when I call it from my scenario (SOAP Adapter Sender) the first result of the lookup will be returned until a forced cache refresh.

Any ideas?

Thank you,

Fabiano.

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Fabiano,

I think your problem is due to static variables inside the Java class. The values are persisted across multiple executions and only a forced cache refresh works.

The reason behind "Interface Mapping Test option" working fine is it would reinitialize your static variable every time but at the runtime i.e. integration engine runtime , the static variables will be those memory locations which would be initialized when a cache refresh was done...

Even I had faced similar problems in module development....

Hope this helps..

-- Amol

Answers (4)

Answers (4)

0 Kudos

Hello Fabiano,

I had the same problem like you had.

The main Problem is that with the example code the request variable is created as NodeList object. In XSLT a variable is somekind of a constant and can't be changed. As the request object is empty after the first request the programm fails at the following line:

Source source = new DOMSource(request.item(0));

So I've created a workaround for this problem.

In the call of the template I've put the request as a parameter object at the template call:

<xsl:with-param name="req">

<rfc:PLM_EXPLORE_BILL_OF_MATERIAL xmlns:rfc="urn:sap-com:document:sap:rfc:functions">

  <APPLICATION>Z001</APPLICATION>

  <FLAG_NEW_EXPLOSION>X</FLAG_NEW_EXPLOSION>

  <MATERIALNUMBER><xsl:value-of select="value"/></MATERIALNUMBER>

  <PLANT>FSD0</PLANT>

  <VALIDFROM><xsl:value-of select="//Recordset/Row[name='DTM-031']/value"/></VALIDFROM>

  <BOMITEM_DATA/>

</rfc:PLM_EXPLORE_BILL_OF_MATERIAL>

</xsl:with-param>

With this change the request will be provided as a String object and not as a NodeList object.

Afterwards the RfcLookup.java has to be changed to the following:

package com.franke.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.
*
* TD:
* 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 - TD: 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 - TD: 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);*/

  

                // TD: Add xml header and remove linefeeds for the request string
                request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+request.replaceAll("[\r\n]+", ""); 
  
                // TD: Get byte Array from request String to send afterwards
                byte[] requestBytes = request.getBytes();
  
               // TD: 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;
         }
     }
}

Then you need to compile and upload this class and it should work.

I hope that this helps you.

Best regards

Till

stefan_grube
Active Contributor
0 Kudos

Apply the bugfix described in note 1029025 to your system.

Regards

Stefan

Former Member
0 Kudos
Former Member
0 Kudos

Hi Chilla!

I´ll be looking for something in your links!

Thanks,

Fabiano.

Former Member
0 Kudos

Hi Amol!

The example code uses a static inner class to help the input. I have chaged it to a normal class but with no success. The problem is still the same.

The code is here:

<a href="https://www.sdn.sap.comhttp://www.sdn.sap.comhttp://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/05a3d62e-0a01-0010-14bc-adc8efd4ee14">https://www.sdn.sap.comhttp://www.sdn.sap.comhttp://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/05a3d62e-0a01-0010-14bc-adc8efd4ee14</a>

Thank you,

Fabiano.

stefan_grube
Active Contributor
0 Kudos

Hi Fabiano,

Could you please let me know, with version/sp level you are using?

Regards

Stefan

Former Member
0 Kudos

Hi Fabiano,

try by removing static from the declaration of execute funtion as:

public Node execute

See if this helps.....

Thanks,

Rajeev Gupta

Message was edited by:

RAJEEV GUPTA

Former Member
0 Kudos

Hello RAJEEV,

I have tryed your suggestion with no success. The XSLT doesn´t "see" the java method if I declare it non-static.

Thank you,

Fabiano.

Former Member
0 Kudos

Stefan,

We´re using the SAP Netweaver 2004s with PI 7.0, SAP J2EE Engine 7.00 PatchLevel and SP10.

Regards,

Fabiano.

Former Member
0 Kudos

Hi Fabiano,

just call these statements in your public static Node execute() function:

tee.close();

tee.finalize();

before return responseNode; statement.

now run your scenario.....see if this helps.....

Thanks,

Rajeev Gupta

stefan_grube
Active Contributor
0 Kudos

Hi Fabiano,

Note 1029025 is for NW04 only. I will see that there will be a fix for NW2004S as well.

I keep you informed.

Regards

Stefan

Former Member
0 Kudos

RAJEEV,

I did a try with the following code:

...

tee.close();

tee = null;

...

But, nothing different happens. I don´t have the finalize() method you have suggested.

Thanks,

Fabiano.

Former Member
0 Kudos

Stefan,

Please let me know if you find out some information about.

Thank you,

Fabiano.

Former Member
0 Kudos

We are experiencing the same problem. We are on PI 7.10 SP8.

We are adviced by SAP to apply note 1049312 however we are in doubt about the impact as in the note SAP states:

Disable the XSL Transformer resuse by XI. Note that this might lead to performance decrease in complex XSLT mappings. No other side effects should be caused by this

Also the note is not released for PI7.1X

Anybody a clue?

Regards,

Emile