Search code examples
javaxmlstreamokhttpstax

Data leak while using StAX with OkHttp3 for parsing large SOAP responses


I'm trying to parse multiple large XML SOAP responses with StAX parser using the following code (tracker is a simple stack for keeping a track of the current XPATH):

XMLInputFactory factory = XMLInputFactory.newInstance()

while (true) {
    /*
     * <-- Request code -->
     */

    Response response = client.newCall(request).execute();
    InputStream responseReader = response.body().byteStream();
    XMLEventReader eventReader = factory.createXMLEventReader(responseReader);

    while (eventReader.hasNext()) {
        XMLEvent event = eventReader.nextEvent();

        if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
            StartElement startElement = event.asStartElement();
            String elementBuffer = startElement.getName().getLocalPart();
            tracker.push(elementBuffer);
            String currentXPath = tracker.getXPath(); //Joins all elements in the stack with '/' as delimiter.

            if (eventReader.peek().getEventType() == XMLStreamConstants.CHARACTERS) {
                String data = eventReader.nextEvent().asCharacters().getData().replace('\n', ' ');

                if (currentXPath.equals("/ABC/DEF/GHI"))
                    // Do something
                if (currentXPath.equals("/JKL/MNO/PQR"))
                    // Do something

                /*
                 * Remaining operations
                 */
            }
        } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
            tracker.pop();
        }
    }

    eventReader.close();
    responseReader.close();
    response.close();
}

Problem: The data String is getting truncated from the end and I'm randomly losing data.

Example: 944aa679441c818d80bd8c7d7001229e would randomly get truncated to 944aa679441c818d80bd8c7 and 100000000 will trim down to 10000.

Can anyone please point out what's wrong with this code? I tried going through StAX & OkHttp documentation but found nothing.

Thanks!


Solution

  • Fixed it:

    XMLInputFactory factory = XMLInputFactory.newInstance()
    
    while (true) {
        /*
         * <-- Request code -->
         */
    
        Response response = client.newCall(request).execute();
        InputStream responseReader = response.body().byteStream();
        XMLEventReader eventReader = factory.createXMLEventReader(responseReader);
    
        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
    
            if (event.getEventType() == XMLStreamConstants.START_ELEMENT) {
                StartElement startElement = event.asStartElement();
                String elementBuffer = startElement.getName().getLocalPart();
                tracker.push(elementBuffer);
                String currentXPath = tracker.getXPath(); //Joins all elements in the stack with '/' as delimiter.
    
                if (eventReader.peek().getEventType() == XMLStreamConstants.CHARACTERS) {
                    String data = "";
                    
                    while(eventReader.peek().getEventType() == XMLStreamConstants.CHARACTERS)
                        data += eventReader.nextEvent().asCharacters().getData().replace('\n', ' ');
    
                    if (currentXPath.equals("/ABC/DEF/GHI"))
                        // Do something
                    if (currentXPath.equals("/JKL/MNO/PQR"))
                        // Do something
    
                    /*
                     * Remaining operations
                     */
                }
            } else if (event.getEventType() == XMLStreamConstants.END_ELEMENT) {
                tracker.pop();
            }
        }
    
        eventReader.close();
        responseReader.close();
        response.close();
    }