4

我有 web 服务来接收和发送附件,我想使用 JAXB 作为编组器,但到目前为止它不能正常工作,因为 JAXB 将消息正文中传入或传出的任何附件作为 base64 字符串内联,消耗了很多内存不足并经常导致 OutOfMemoryError。我正在概述我的设置和修复尝试,希望有人能帮助我把它做好。

Axiom 是我选择 SAAJ 作为消息工厂的选择,因为我必须处理大附件。我可以成功地将 JAXB 用作端点方法的参数和返回类型的编组器,除非涉及附件(内联问题)。这是我的设置:

网络服务配置 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;
    }
}

因此,此代码有效,但与附件不同。我正在寻找一些工作解决方案:

显然,最好的帮助来自我发布的关于 WSS4J 发生的这个内联问题的另一个 SO question 。Blaise Doughan 说我需要AttachmentMarshallerAttachmentUnmarshaller设置(un)marshaller 来正确处理它,就像他在他的博客中发布的那样


所以,我假设附件编组器是解决这个问题的关键。

要将它们设置在(un)marshaller 上,我没有其他办法,只能在给定的(un)marshaller 上设置附件 marshaller(我为它们复制了 Doughan 的代码Jaxb2MarshallerinitJaxbMarshallerinitJaxbUnmarshaller

但是我自己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 类是创建但从未使用过,我不知道为什么,所以我仍然无法测试AttachmentMarshallers 是否可以解决问题。

这就是我现在能说的。有很多方法可以尝试:

  • 找出MyJaxb2Marshaller被忽略的原因,这可能是最简单的;
  • AttachmentMarshaller如果s 不能解决它,则修复 JAXB 附件内联其他方式,我不知道那会是什么;
  • 用其他编组器替换 JAXB,效果一样好(主要是 Axiom 支持,可能是 WSS4J)。

我在这个问题上待了很长时间,我一定错过了明显的解决方案。任何帮助都是最受欢迎的。

谢谢!


库版本:

  • Spring 3.1.0 (core, beans, oxm 等)
  • Spring WS 2.1.0(核心和 Spring XML)
  • StAX2 2.1
  • WoodSToX 3.2.9 (wstx)
  • JAXB 2.2.5-2 (API+impl)
  • Apache Axiom 1.2.13 (API+impl+c14n+dom)
  • Apache Mime4j 0.7.2(核心)

应用服务器是带有 Java 1.6.0u14 的 Oracle 11g R1 Patchset 1。

4

0 回答 0