Spring WS with Axiom: JAXB is inlining MTOM attachments

和自甴很熟 提交于 2019-12-20 02:52:22

问题


I have webservices to receive and send attachments, and I'd like to use JAXB as marshaller, but so far it is not working right, as JAXB inlines any attachment coming in or going out in the message body as base64 strings, consuming a lot of memory and frequently leading to OutOfMemoryError. I'm outlining my setup and fix attempts, and hope someone can help me get it right.

Axiom is my choice over SAAJ as message factory, as I have to handle big attachments. I can successfully use JAXB as a marshaller for parameters and return types of endpoint methods, except when an attachment is involved (inline issue). This is my setup for it:

Webservices config 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>

Part of my 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>

My endpoint class:

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;
    }
}

So, this code works, but not as it would with attachments. I'm searching for some time for a workign solution:

  • Spring Forums: correct MTOM handling? : suggests extending some Axiom classes, but the code changed considerably ever since (2008), and I couldn't get it working;
  • Spring Forums: Response-Attachment/Saaj/Jaxb : possible cause by a JVM bug fixed in 1.6u14, which is the one used by my Weblogic version (plus it didn't work for the topic creator);
  • Spring Forums: sending large attachments with Spring-WS client : someone solved using Axis2 directly bypassing Spring WS, which is not the point;
  • Stackoverflow: Spring-WS webservice with MTOM attachement - Hello world test : same issue as mine, 2 weeks old, no answers;

Apparently the best help came from this other SO question I posted about this inlining problem happening with WSS4J. Blaise Doughan said that I'd need AttachmentMarshaller and AttachmentUnmarshaller set on the (un)marshaller to get it handled properly, like he posted in his blog.


So, I'm assuming attachment marshallers are the key to solve this issue.

To set them on the (un)marshaller, I saw no other way but extend Jaxb2Marshaller and overide initJaxbMarshaller and initJaxbUnmarshaller, setting attachment marshallers (I copied Doughan's code for them) on the given (un)marshaller.

But my own Jaxb2Marshaller is not being used, not even when setting it manually to 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>

This marshaller class is created but never used, I don't know why, so I still couldn't test if AttachmentMarshallers can solve the issue.

This is all I can say for now. There are quite a few approaches to try:

  • find out why MyJaxb2Marshaller is being ignored, probably the easiest;
  • fix JAXB attachment inlining some other way if AttachmentMarshallers won't solve it, and I don't know what that would be;
  • replace JAXB with other marshaller, that works just as well (mainly Axiom support, possibly WSS4J).

I'm on a long time on this issue, and I must be missing the obvious solution. Any help is most welcome.

Thanks!


Library versions:

  • Spring 3.1.0 (core, beans, oxm and such)
  • Spring WS 2.1.0 (core and 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 (core)

App server is Oracle 11g R1 Patchset 1 with Java 1.6.0u14.

来源:https://stackoverflow.com/questions/11564899/spring-ws-with-axiom-jaxb-is-inlining-mtom-attachments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!