Spring WS z Axiom: JAXB umieszcza załączniki MTOM
Mam usługi sieciowe do odbierania i wysyłania załączników, i chciałbym używać JAXB jako marshallera, ale do tej pory nie działa on prawidłowo, ponieważ JAXB zapisuje wszelkie załączniki przychodzące lub wychodzące w treści wiadomości jako łańcuchy base64, zużywając dużo pamięci i często prowadzi do OutOfMemoryError. Opisuję konfigurację i naprawiam próby i mam nadzieję, że ktoś może mi pomóc.
Axiom jest moim wyborem na SAAJ jako fabrykę wiadomości, ponieważ muszę obsługiwać duże załączniki. Mogę z powodzeniem używać JAXB jako marshallera dla parametrów i typów zwracanych metod końcowych, z wyjątkiem sytuacji, gdy dotyczy to załącznika (problem wbudowany). Oto moja konfiguracja:
XML konfiguracji Webservices:
<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>
Część mojego 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>
Moja klasa punktu końcowego:
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;
}
}
Zatem ten kod działa, ale nie tak, jak w przypadku załączników. Poszukam pewnego czasu, aby znaleźć rozwiązanie:
Spring Forum: poprawna obsługa MTOM? : sugeruje rozszerzenie niektórych klas aksjomatów, ale kod zmienił się znacznie od tego czasu (2008) i nie mogłem go uruchomić;Spring Forum: Załącznik-odpowiedź / Saaj / Jaxb : możliwą przyczyną jest błąd JVM naprawiony w 1.6u14, który jest używany przez moją wersję Weblogic (plus to nie działa dla twórcy tematu);Wiosenne fora: wysyłanie dużych załączników za pomocą klienta Spring-WS : ktoś rozwiązał problem używając Axis2 bezpośrednio omijając Spring WS, co nie jest celem;Stackoverflow: serwis internetowy Spring-WS z załącznikiem MTOM - Hello world test : ten sam problem co mój, 2 tygodnie, brak odpowiedzi;Najwyraźniej pochodziła najlepsza pomocto inne pytanie SO Napisałem o tym problemie inliningu z WSS4J. Blaise Doughan powiedział, że potrzebujęAttachmentMarshaller
iAttachmentUnmarshaller
ustawić na (un) marshallera, aby prawidłowo go obsłużyć,tak jak napisał na swoim blogu.
Zakładam więc, że kluczem do rozwiązania tego problemu są rozdzielacze załączników.
Aby ustawić je na (nie) marszałku, nie widziałem innego wyjścia, jak tylko rozszerzyćJaxb2Marshaller
i nadrzędnyinitJaxbMarshaller
iinitJaxbUnmarshaller
, ustawiając strażników załogi (skopiowałem dla nich kod Doughana) na danym (nie) maszynie.
Ale mój własnyJaxb2Marshaller
nie jest używany, nawet podczas ręcznego ustawianiasws: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>
Ta klasa marshallera jest tworzona, ale nigdy nie używana, nie wiem dlaczego, więc nadal nie mogłem sprawdzić, czyAttachmentMarshaller
s może rozwiązać problem.
To wszystko, co mogę teraz powiedzieć. Istnieje kilka podejść do wypróbowania:
Dowiedz się dlaczegoMyJaxb2Marshaller
jest ignorowany, prawdopodobnie najłatwiejszy;napraw załącznik JAXB, wstawiając go w inny sposób, jeśliAttachmentMarshaller
s nie rozwiąże tego i nie wiem, co by to było;zastąp JAXB innym marshallerem, który działa równie dobrze (głównie wsparcie Axiom, być może WSS4J).Długo poświęcam temu zagadnieniu i muszę tęsknić za oczywistym rozwiązaniem. Każda pomoc jest mile widziana.
Dzięki!
Wersje biblioteki:
Wiosna 3.1.0 (rdzeń, fasola, oxm itp.)Wiosna WS 2.1.0 (rdzeń i Spring XML)StAX2 2.1WoodSToX 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 (rdzeń)Serwer aplikacji to Oracle 11g R1 Patchset 1 z Java 1.6.0u14.