我有web服务来接收和发送附件,我想使用JAXB作为编组程序,但到目前为止,它无法正常工作,因为JAXB将任何作为base64字符串输入或出现在消息正文中的附件,消耗大量内存并经常导致OutOfMemoryError。我正在概述我的设置和修复尝试,并希望有人可以帮助我做到正确。
Axiom是我选择SAAJ作为留言工厂,因为我必须处理大附件。我可以成功地使用JAXB作为参数的编组器并返回端点方法的类型,除非涉及附件(内联问题)。这是我的设置:
Webservices配置XML:
<beans xmlns=...>
<context:component-scan base-package="com.example.webservice" />
<sws:annotation-driven />
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.example.webservice.oxm.FileTestResponse</value>
<value>com.example.webservice.oxm.FileTestRequest</value>
</list>
</property>
<property name="mtomEnabled" value="true"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="true"/>
<property name="attachmentCaching" value="true"/>
</bean>
<sws:dynamic-wsdl id="fileTest" portTypeName="fileTest" locationUri="/webservice/fileTest/" targetNamespace="http://example.com/webservice/definitions" >
<sws:xsd location="/WEB-INF/fileTest.xsd" />
</sws:dynamic-wsdl>
</beans>
我的部分XSD:
<!-- I generate the marshalling classes with XJB, and using
xmime:expectedContentTypes it correctly creates mtomData field
with DataHandler type instead of byte[] -->
<xs:element name="fileTestRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="mtomData" type="xs:base64Binary"
xmime:expectedContentTypes="application/octet-stream"/>
</xs:sequence>
</xs:complexType>
</xs:element>
我的端点类:
package com.example.webservice;
import ...
@Endpoint
@Namespace(prefix = "s", uri = FileTestEndpoint.NAMESPACE)
public class FileTestEndpoint {
public static final String NAMESPACE = "http://example.com/webservice/schemas";
@PayloadRoot(localPart = "fileTestRequest", namespace = NAMESPACE)
@ResponsePayload
public FileTestResponse fileTest(@RequestPayload FileTestRequest req) throws IOException {
// req.getMtomData() and do something with it
FileTestResponse resp = new FileTestResponse();
DataHandler dataHandler = new DataHandler(new ByteArrayDataSource("my file download data".getBytes(), "text/plain"));
resp.setData(dataHandler);
return resp;
}
}
因此,此代码有效,但与附件无关。我正在寻找一些工作解决方案的时间:
显然最好的帮助来自this other SO question我发布了关于WSS4J发生的这个内联问题。 Blaise Doughan说我需要AttachmentMarshaller
和AttachmentUnmarshaller
设置(联合国)marshaller才能正确处理like he posted in his blog。
所以,我假设附件编组是解决这个问题的关键。
要在(联合国)marshaller上设置它们,除了Jaxb2Marshaller
并覆盖initJaxbMarshaller
和initJaxbUnmarshaller
之外,我没有别的办法,设置附件marshallers(我为他们复制了Doughan的代码)在给定(非)marshaller上。
但是我自己的Jaxb2Marshaller
没有被使用,即使手动设置为sws:annotation-driven
也没有:
<sws:annotation-driven marshaller="jaxb2Marshaller" unmarshaller="jaxb2Marshaller"/>
<bean id="jaxb2Marshaller" class="com.example.webservice.MyJaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.example.webservice.oxm.FileTestResponse</value>
<value>com.example.webservice.oxm.FileTestRequest</value>
</list>
</property>
<property name="mtomEnabled" value="true"/>
</bean>
这个marshaller类已经创建但从未使用过,我不知道为什么,所以我仍然无法测试AttachmentMarshaller
是否可以解决问题。
这就是我现在可以说的全部内容。有很多方法可以尝试:
MyJaxb2Marshaller
被忽略,可能是最简单的; AttachmentMarshaller
无法解决问题,我在这个问题上已经很长时间了,我一定错过了明显的解决方案。 我们非常欢迎任何帮助。
谢谢!
图书馆版本:
App服务器是带有Java 1.6.0u14的Oracle 11g R1 Patchset 1。