Spring WS + Wss4jSecurityInterceptor + MTOM memory issues
Asked Answered
O

0

1

This seems to be somewhat a longstanding question, and no definitive solution so far: situations where your incoming MTOM messages get inlined to the SOAP message, crashing the application due to memory usage.

I'm creating a file upload webservice with Spring WS (2.1) using Apache Axiom (1.2.13) because the files I receive are big:

<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
    <property name="payloadCaching" value="true"/>
    <property name="attachmentCaching" value="true"/>
</bean>

I'm using JAXB (2.2.5) for XML data marshalling, but it inlines attachments, so for endpoints that handle attachments I use SoapMessage directly; not what I would prefer, but acceptable. Up to this point is fine with this setup, and I can upload very big files. The problem is that I also need authentication, for which I'm using Apache WSS4J 1.6.6:

<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
    <property name="validationActions" value="UsernameToken"/>
    <property name="securementActions" value="NoSecurity"/>
</bean>

When the interceptor does the message validation, it also inlines the attachment data to the body of the message, eating lots of memory and generating OutOfMemoryError on reasonably sized messages:

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:3209) ~[na:1.6.0_14]
    at java.lang.String.<init>(String.java:215) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.xni.XMLString.toString(XMLString.java:185) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.characters(AbstractDOMParser.java:1188) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:463) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283) ~[na:1.6.0_14]
    at weblogic.xml.jaxp.RegistryDocumentBuilder.parse(RegistryDocumentBuilder.java:163) ~[weblogic.jar:10.3.2.0]
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124) ~[na:1.6.0_14]
    at org.springframework.ws.soap.axiom.support.AxiomUtils.toDocument(AxiomUtils.java:133) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.axiom.AxiomSoapMessage.getDocument(AxiomSoapMessage.java:201) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor.validateMessage(Wss4jSecurityInterceptor.java:561) ~[spring-ws-security-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleRequest(AbstractWsSecurityInterceptor.java:123) ~[spring-ws-security-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor.handleRequest(DelegatingSmartEndpointInterceptor.java:78) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:224) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:173) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:59) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:221) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) ~[org.springframework.web.servlet-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) ~[org.springframework.web.servlet-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) ~[javax.servlet_1.0.0.0_2-5.jar:2.5]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) ~[javax.servlet_1.0.0.0_2-5.jar:2.5]
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3591) ~[weblogic.jar:10.3.2.0]
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) ~[com.bea.core.weblogic.security.identity_1.1.2.0.jar:1.1.2.0]

I haven't found a way to fix this undesired inlining so far. I don't want to read and handle the header manually, it would make WSS4J pointless, and my code less flexible to handle future requirements.

This thread suggests fooling the interceptor into using a copy of the message containing only the header, but I couldn't implement it (it is a few years old, the API may be changed). This would probably forbid the use of encrypted and signed messages (as a reply points out), but so far not a requirement for me. This other thread suggests sticking with Axiom 1.2.8, which did nothing, and also setting the validateRequest flag on the Axiom factory to false (this one sounds strange, as it disables security - no error but no security, what would be the point of it?).

So, anybody can help me with a solution to this issue? Fixing JAXB, tricking the WSS4J interceptor, or some other solution? Any help is welcome!

Thanks!

Osi answered 18/7, 2012 at 14:5 Comment(4)
JAXB allows an AttachmentMarshaller to be set on a Marshaller and an AttachmentUnmarshaller to be set on an Unmarshaller. These are provided by the JAX-WS implementation. The JAXB implementation will give these attachment handlers a chance to handle the binary data, if they don't they will inline the binary data (see: blog.bdoughan.com/2011/03/…). My suspicion is that your issue is related to Spring WS.Cleric
@BlaiseDoughan Thanks, I wasn't aware of that. I didn't include it in this question, but I was having problems to create webservices for file download too, that were also inlining the files. With your advice I hope I can fix it too. Looks like there are no methods to plug them, so I'll try to extend Spring's Jaxb2Marshaller and set the (un)marshaller in initJaxbMarshaller and initJaxbUnmarshaller. I'll post a reply as soon as I have something =)Osi
@BlaiseDoughan I couldn't try the attachment marshallers, couldn't wire them properly. I created a new question here specifically about this JAXB issue. I'd appreciate your help, if you could. #11565399Osi
@Osi - Can you please share atleast the pseudo configuration of your full working file. I am unable to get Axiom and wss4j working together. Facing error given at forum.springsource.org/… and also at #17633187 . Please help. ThanksEllene

© 2022 - 2024 — McMap. All rights reserved.