Search code examples
javaweb-serviceswebsphere

How to fix java heap space on websphere when sending invalid xml


when I send invalid xml to my web services on websphere server, I get java heap space:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/">
   <soap:Header/>
   <soap:Body>
       <MyElementsomething</MyElement>

   </soap:Body>
</soap:Envelope>

with the element

   <MyElement>something</MyElement>

Everything works ok

Exception:

java.lang.OutOfMemoryError: Java heap space
        at com.ibm.ws.webservices.utils.BAIS.create(BAIS.java:74) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.utils.WebServicesInputSource.getBAISContent(WebServicesInputSource.java:744) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.utils.WebServicesInputSource.getByteArrayContent(WebServicesInputSource.java:710) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.utils.WebServicesInputSource.getStringContent(WebServicesInputSource.java:674) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.utils.WebServicesInputSource.getString(WebServicesInputSource.java:425) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.engine.SOAPPart._getSOAPEnvelope(SOAPPart.java:1090) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.engine.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:628) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.engine.SOAPPart.getEnvelope(SOAPPart.java:656) ~[com.ibm.ws.runtime.jar:?]
        at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:155) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.soap.saaj.SaajSoapMessage.getSaajVersion(SaajSoapMessage.java:257) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:342) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.soap.saaj.SaajSoapMessage.<init>(SaajSoapMessage.java:117) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:186) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:60) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:90) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
        at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:86) ~[spring-ws-core-2.1.0.RELEASE.jar:?]

EDIT:

nobody know ?

PS: spring validation doesnt help because it is after websphere stuff. When I send invalid xml agains xsd (for example string instead of number) then it works:

2015-02-18 10:12:46.128 [WebContainer : 8] WARN  cz.isvs.ais3.ws.interceptor.ServerPayloadValidatingInterceptor - XML validation error on request: cvc-datatype-valid.1.2.1: 'b' is not a valid value for 'integer'.
2015-02-18 10:12:46.128 [WebContainer : 8] WARN  cz.isvs.ais3.ws.interceptor.ServerPayloadValidatingInterceptor - XML validation error on request: cvc-type.3.1.3: The value 'b' of element 'urn1:Ais' is not valid.

because of WebServiceMessageReceiverObjectSupport.class:

86            WebServiceMessage request = connection.receive(getMessageFactory()); // here occurs out of memory
87            MessageContext messageContext = new DefaultMessageContext(request, getMessageFactory());
88            receiver.receive(messageContext); // and in this method are interceptor which validate request

PS2:

when I tried to increase heap space from 2gb to 4gb there is another exception on the same spot:

java.lang.IndexOutOfBoundsException
        at java.io.PushbackInputStream.read(PushbackInputStream.java:181) ~[?:1.7.0]
        at java.io.FilterInputStream.read(FilterInputStream.java:133) ~[?:1.7.0]
        at com.ibm.ws.webservices.utils.WebServicesInputSource$FilterIS.read(WebServicesInputSource.java:805) ~[com.ibm.ws.runtime.jar:?]
        at com.ibm.ws.webservices.utils.BAIS.create(BAIS.java:77) ~[com.ibm.ws.runtime.jar:?]

PS3:

this is correct behavior with sun java:

Caused by: org.xml.sax.SAXParseException: The element type "urn:ZadostInfo" must be terminated by the matching end-tag "</urn:ZadostInfo>".
        at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) ~[?:?]
        at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) ~[?:?]
        at org.xml.sax.helpers.XMLFilterImpl.parse(Unknown Source) ~[?:?]
        at org.apache.xalan.transformer.TransformerIdentityImpl.transform(Unknown Source) ~[?:?]
        at com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:411) ~[?:1.7.0]
        at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:115) ~[?:1.7.0]
        at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:80) ~[?:1.7.0]
        at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:140) ~[?:1.7.0]
        at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:155) ~[spring-ws-core-2.1.2.RELEASE.jar:?]

Solution

  • I tried to fix this by my own. I examined how spring-ws validate xml and tried to do it before websphere. Here is code. I test it and it is working for me.

    public class SaajSoapMessageValidatorFactory extends SaajSoapMessageFactory {
    
        @Override
        public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
            InputStream original;
    
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                IOUtils.copy(inputStream, baos);
    
                original = new ByteArrayInputStream(baos.toByteArray());
                InputStream validate = new ByteArrayInputStream(baos.toByteArray());
    
                try {
                    ValidatorResources validator = new XmlValidatorResources(validate);
                    validator.process();
                } catch (Exception parseException) {
                    throw new InvalidXmlException("Could not parse XML", parseException);
                } finally {
                    IOUtils.closeQuietly(validate);
                }
            } finally {
                IOUtils.closeQuietly(inputStream);
            }
    
            return super.createWebServiceMessage(original);
        }
    }
    
    
    
    public class XmlValidatorResources extends ValidatorResources {
    
        private static final long serialVersionUID = 1L;
    
        public XmlValidatorResources(InputStream in) throws IOException, SAXException {
            Digester digester = new Digester();
            digester.push(this);
            digester.parse(in);
        }
    
    }
    

    and in spring context I add:

    <bean id="messageFactory" class="cz.isvs.ais3.ws.validator.SaajSoapMessageValidatorFactory" />