Budowanie dużych komunikatów MTOM / XOP za pomocą JAX-WS
Mam pytanie dotyczące korzystania z MTOM / XOP z JAX-WS. Piszę serwis internetowy, który wysyła duże ilości danych binarnych. Klient żąda pewnej liczby plików, a serwer zwraca pliki w odpowiedzi.
Potrafię go poprawnie zbudować, aby poprawnie implementował XOP, ale wpadam na problemy związane z pamięcią, ponieważ przechowuje onCały odpowiedź w pamięci przed wysłaniem. Pliki wysyłane przez tę usługę internetową mogą zostać pobranebardzo duże (jak gigabajty duże), więc przechowywanie odpowiedzi w pamięci nie jest opcją.
Ta strona Oracle (i wraz zten) wydaje się rozwiązywać ten problem, ale po prostu tego nie rozumiem. Myślę, że używająDataHandler
obiekt, aby przesłać strumieniowo żądanie / odpowiedź, ale nie potrafię określić, w jaki sposób tworzą instancję.
Generuję pliki klas JAX-WS z istniejącego pliku WSDL za pomocąwsimport
. Używam JAX-WS RI 2.1.6 z Javą 6.
Jak wysłać odpowiedź, gdy ją buduję, bez konieczności zapisywania wszystkich w pamięci?
Z góry dziękuje za twoją pomoc.
AKTUALIZACJA 12/17: Dodałem następujące atrybuty do elementu schematu w WSDL, który przechowuje dane binarne. To powodujewsimport
dodać aDataHandler
obiekt do klasy JAXB. ZAFileDataHandler
można następnie dodać do odpowiedzi, zamiast dodawać całą zawartość pliku, pozwalając serwerowi przesyłać strumieniowo zawartość każdego pliku, zamiast trzymać je wszystkie w pamięci:
xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
xmime:expectedContentTypes="application/octet-stream"
Serwer poprawnie buduje odpowiedź teraz, a klient poprawnie zapisuje każdy plik na dysku, gdy odbierze żądanie. Jednak klient nadal odczytuje całą odpowiedź do pamięci z jakiegoś powodu.
Kod serwera (SIB):
@MTOM
@StreamingAttachment(parseEagerly = true, memoryThreshold = 4000000L)
@WebService(...)
public class DownloadFilesPortTypeImpl implements DownloadFilesPortType {
@Override
public FileSetResponseType downloadFileSet(FileSetRequestType body) {
FileSetResponseType response = new FileSetResponseType();
for (FileRequest freq : body.getFileRequest()){
try{
//find the file on disk
File file = findFile(freq.getFileId());
//read the file data into memory
byte[] fileData;
{
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buf[] = new byte[8192];
int read;
while ((read = in.read(buf)) != -1){
out.write(buf, 0, read);
}
in.close();
out.close();
fileData = out.toByteArray();
}
//add the file to the response
FileResponse fresp = new FileResponse();
fresp.setFileId(freq.getFileId());
fresp.setData(fileData); //<-- type "xs:base64Binary"
response.getFileResponse().add(fresp);
}
catch (IOException e){
}
}
return response;
}
}
Kod klienta:
DownloadFilesService service = new DownloadFilesService();
MTOMFeature mtomFeature = new MTOMFeature();
StreamingAttachmentFeature stf = new StreamingAttachmentFeature(null, true, 4000000L);
DownloadFilesPortType port = service.getDownloadFilesPortSoap12(mtomFeature, stf);
FileSetRequestType request = new FileSetRequestType();
FileRequest freq = new FileRequest();
freq.setFileId("1234");
request.getFileRequest().add(freq);
freq = new FileRequest();
freq.setFileId("9876");
request.getFileRequest().add(freq);
//...
FileSetResponseType response = port.downloadFileSet(request); //reads entire response into memory
for (FileResponse fres : response.getFileResponse()){
byte[] data = fres.getFileData();
//...
}