3

I have a JBoss web service (5.1) using EJB3 to run apps for dao updates/inserts on our MSSQL server.

Part of the app setup includes a custom SOAPHandler, which is used to parse the xml from the message in ByteArray[Output/Input]Stream and print it to the server log.

This works fine most of the time, but recently we took on a new client who is sending large amounts of data, and due to a slim (vitually non-existant) budget, I have to run our test/integration service on an old pc (trust me, i didn't want to).

Sure enough, before long i encountered:

    2012-11-21 14:20:40,128 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost]. *removed* -5) Servlet.service() for servlet *MyIface* threw exception
java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2786)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
    at com.sun.xml.bind.v2.runtime.output.UTF8XmlOutput.write(UTF8XmlOutput.java:394)
    at com.sun.xml.bind.v2.runtime.output.UTF8XmlOutput.write(UTF8XmlOutput.java:386)
    at com.sun.xml.bind.v2.runtime.output.UTF8XmlOutput.endTag(UTF8XmlOutput.java:273)
    at com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl$Element.endElement(NamespaceContextImpl.java:493)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.endElement(XMLSerializer.java:310)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
    at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
    at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
    at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
    at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)

Could someone give me some tips about chunked parsing here please? I've check this thread amongst others, and my problem sounds similar to this, but i don't know which api/approach to use.

Here's my handler:

@SuppressWarnings("rawtypes")
public class MyHandler extends GenericSOAPHandler {

    private void print(InputStream input, OutputStream out) throws Exception {
        try {
            DocumentBuilder parser;
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            parser = factory.newDocumentBuilder();
            Document document = parser.parse(input);
            Transformer serializer = TransformerFactory.newInstance().newTransformer();
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            serializer.transform(new DOMSource(document), new StreamResult(out));
        } catch (TransformerException e) {
            // A fatal error occurred
            throw new Exception(e);
        }
    }


    @Override
    protected boolean handleInbound(MessageContext msgContext) {
        SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
        SOAPMessage soapMessage = soapMessageCtx.getMessage();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            soapMessage.writeTo(outputStream);
            byte[] array = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
            System.out.println("SOAP request message:\n");
            print(inputStream, System.out);
        } catch (SOAPException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    protected boolean handleOutbound(MessageContext msgContext) {
        SOAPMessageContext soapMessageCtx = (SOAPMessageContext) msgContext;
        SOAPMessage soapMessage = soapMessageCtx.getMessage();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            soapMessage.writeTo(outputStream);
            byte[] array = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(array);
            System.out.println("SOAP response message:\n");
            print(inputStream, System.out);
        } catch (SOAPException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

}

Thankyou

Community
  • 1
  • 1
Rich
  • 867
  • 7
  • 12

0 Answers0