这似乎是一个长期存在的问题,到目前为止还没有确定的解决方案:传入的 MTOM 消息被内联到 SOAP 消息的情况,由于内存使用而导致应用程序崩溃。
我正在使用 Apache Axiom (1.2.13) 使用 Spring WS (2.1) 创建文件上传 Web 服务,因为我收到的文件很大:
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="true"/>
<property name="attachmentCaching" value="true"/>
</bean>
我使用 JAXB (2.2.5) 进行 XML 数据编组,但它内联附件,因此对于处理我SoapMessage
直接使用的附件的端点;不是我想要的,但可以接受。到目前为止,这个设置很好,我可以上传非常大的文件。问题是我还需要身份验证,为此我使用的是 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>
当拦截器进行消息验证时,它还将附件数据内联到消息正文中,占用大量内存并生成OutOfMemoryError
合理大小的消息:
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]
到目前为止,我还没有找到解决这种不受欢迎的内联的方法。我不想手动读取和处理标题,这会使 WSS4J 毫无意义,并且我的代码在处理未来需求方面的灵活性降低。
该线程建议欺骗拦截器使用仅包含标头的消息副本,但我无法实现它(它已有几年历史,API 可能会更改)。这可能会禁止使用加密和签名的消息(正如回复指出的那样),但到目前为止对我来说不是必需的。这个另一个线程建议坚持使用 Axiom 1.2.8,它什么也没做,并将validateRequest
Axiom 工厂上的标志设置为false
(这听起来很奇怪,因为它禁用了安全性 - 没有错误但没有安全性,这有什么意义呢? )。
那么,任何人都可以帮助我解决这个问题吗?修复 JAXB、欺骗 WSS4J 拦截器或其他解决方案?欢迎任何帮助!
谢谢!