JAX-WS での MTOM/XOP の使用について質問があります。大量のバイナリ データを送信する Web サービスを作成しています。クライアントは多数のファイルを要求し、サーバーは応答でファイルを返します。
XOPを正しく実装するように応答を正しく構築することはできますが、送信する前に応答全体をメモリに保存するため、メモリ関連の問題が発生します。この Web サービスが送信するファイルは非常に大きくなる可能性があるため (ギガバイト単位など)、応答をメモリに格納することはできません。
このオラクルのウェブサイト(およびこれと一緒に)はこの問題を解決しているようですが、私はそれを理解していません. オブジェクトを使用してリクエスト/レスポンスをストリーミングしていると思いますDataHandler
が、インスタンス化する方法がわかりません。
を使用して、既存の WSDL から JAX-WS クラス ファイルを生成していますwsimport
。Java 6 で JAX-WS RI 2.1.6 を使用しています。
最初にすべてをメモリに保存することなく、ビルド中に応答を送信するにはどうすればよいですか?
よろしくお願いします。
UPDATE 12/17:バイナリ データを保持する WSDL のスキーマ要素に次の属性を追加しました。これにより、オブジェクトが JAXB クラスwsimport
に追加されます。DataHandler
次に、ファイルの内容全体を追加する代わりに、応答にAFileDataHandler
を追加して、サーバーが各ファイルの内容をすべてメモリに保持する代わりにストリーミングできるようにします。
xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
xmime:expectedContentTypes="application/octet-stream"
そのため、サーバーは応答を正しく作成し、クライアントは要求を受信したときに各ファイルをディスクに適切に保存します。ただし、何らかの理由で、クライアントは引き続き応答全体をメモリに読み込みます。
サーバーコード (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;
}
}
クライアントコード:
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();
//...
}