Spring WS с Axiom: JAXB встраивает вложения MTOM

У меня есть веб-сервисы для получения и отправки вложений, и я хотел бы использовать 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;
    }
}

Итак, этот код работает, но не так, как с вложениями. Я ищу какое-то время для рабочего решения:

По-видимому, лучшая помощь пришла из этот другой вопрос SO, который я опубликовал об этой проблеме встраивания происходит с WSS4J. Блейз Доуган сказал, что мне нужно установить AttachmentMarshaller и AttachmentUnmarshaller на (не)маршаллере, чтобы он правильно обрабатывался, как он написал в своем блоге.


Итак, я предполагаю, что упорядочители вложений являются ключом к решению этой проблемы.

Чтобы установить их на (не)маршаллере, я не видел другого пути, кроме как расширить Jaxb2Marshaller и переопределить initJaxbMarshaller и initJaxbUnmarshaller, установив маршалеры вложений (я скопировал для них код Дугана) на заданный (не)маршаллер.

Но мой собственный 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 игнорируют, наверное, проще всего;
  • исправить встраивание вложения JAXB каким-либо другим способом, если AttachmentMarshallers не решит эту проблему, и я не знаю, что это может быть;
  • замените JAXB на другой маршаллер, который работает так же хорошо (в основном поддержка Axiom, возможно, WSS4J).

Я долго занимаюсь этим вопросом, и мне, должно быть, не хватает очевидного решения. Любая помощь приветствуется.

Спасибо!


Версии библиотеки:

  • Spring 3.1.0 (ядро, beans, oxm и т. д.)
  • Spring WS 2.1.0 (ядро и Spring XML)
  • StAX2 2.1
  • WoodSToX 3.2.9 (wstx)
  • JAXB 2.2.5-2 (API+внедрение)
  • Apache Axiom 1.2.13 (API+импл+c14n+дом)
  • Apache Mime4j 0.7.2 (ядро)

Сервер приложений — Oracle 11g R1 Patchset 1 с Java 1.6.0u14.


person mdrg    schedule 19.07.2012    source источник
comment
Помогает ли следующее? stackoverflow.com/questions/6433762/   -  person bdoughan    schedule 19.07.2012
comment
@BlaiseDoughan Я попробовал этот код, я могу успешно добавить вложение, но я не могу заставить поле data ссылаться на него с помощью XOP, оно как всегда встраивает данные, несмотря на то, что те же данные прикреплены. В старых сообщениях (с 2007 по 2010 год) на форумах Spring говорится, что поддержка MTOM была доступна только для SAAJ, что и использовалось в ответе, который вы только что опубликовали. Код для AxiomSoapMessage.convertToXopPackage все еще пуст, так что с тех пор он кажется нетронутым. Я не уверен, как мне нужно исправить Axiom на Spring, чтобы заставить работать ответ на вложение... возможно, это также понадобится для запросов на вложение.   -  person mdrg    schedule 19.07.2012
comment
В реализации Java EE JAX-WS реализация JAX-WS будет напрямую взаимодействовать с JAXB и сама устанавливать обработчики вложений, после чего все будет работать автоматически. Я пытаюсь собрать воедино то, что делает Spring WS.   -  person bdoughan    schedule 19.07.2012
comment
Извините, что не ответил раньше. Я заставил его работать в конце концов. См. обновление в другой моей теме (stackoverflow.com/questions/11316023/) . Если вы все еще боретесь, дайте мне знать, и я вышлю вам пример рабочей копии по электронной почте.   -  person ziggy    schedule 20.07.2012
comment
@ziggy Спасибо за решение. Это работает, но только для SAAJ. Буду искать с Аксиомой =)   -  person mdrg    schedule 20.07.2012
comment
@mdrg Вам удалось решить эту проблему с помощью аксиомы? У меня такая же проблема.   -  person AJJ    schedule 11.04.2016
comment
@AJJ Нет, к сожалению, нет. Я работал над этим, избегая какой-либо обработки сообщений с вложениями, и оставил все как есть, потому что у меня больше не было времени посвятить этому вопросу. Я не могу точно сказать, что я сделал, потому что у меня больше нет доступа к этому коду. Извини.   -  person mdrg    schedule 11.04.2016