Skip to Content
author's profile photo Former Member
Former Member

XSLT and Java lookup cache

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.

Add a comment
10|10000 characters needed characters exceeded

Assigned Tags

Related questions

5 Answers

  • Best Answer
    author's profile photo Former Member
    Former Member
    Posted on Feb 12, 2007 at 04:37 AM

    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

    Add a comment
    10|10000 characters needed characters exceeded

  • Posted on Feb 19, 2007 at 01:54 PM

    Apply the bugfix described in note 1029025 to your system.

    Regards

    Stefan

    Add a comment
    10|10000 characters needed characters exceeded

  • author's profile photo Former Member
    Former Member
    Posted on Feb 13, 2007 at 02:48 AM
    Add a comment
    10|10000 characters needed characters exceeded

    • Former Member Former Member

      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

  • author's profile photo Former Member
    Former Member
    Posted on Feb 19, 2007 at 10:42 AM
    Add a comment
    10|10000 characters needed characters exceeded

  • Posted on Jul 03, 2012 at 12:35 PM

    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

    Add a comment
    10|10000 characters needed characters exceeded

Before answering

You should only submit an answer when you are proposing a solution to the poster's problem. If you want the poster to clarify the question or provide more information, please leave a comment instead, requesting additional details. When answering, please include specifics, such as step-by-step instructions, context for the solution, and links to useful resources. Also, please make sure that you answer complies with our Rules of Engagement.
You must be Logged in to submit an answer.

Up to 10 attachments (including images) can be used with a maximum of 1.0 MB each and 10.5 MB total.