SOAP Client for Downloading Attachments - Streaming
We have seen uploading of larger data files using SOAP with attachments in the previous post(Upload attachments using SOAP). We will see how to download/stream larger files from SOAP web service.
Java Mail API Problem
The SOAP web service client for downloading attachments we will be discussing uses the MimeMessage structure but we will avoid using the JAVA MAIL package as it is not efficient while downloading the contents. If you use MimeMessage java api to get the MimeBodyPart then you'll be in trouble as MimeMessage loads the entire content as byte array into memory for calculating the size and number of MimeBodyParts. So we will avoid using it for larger files if you have small JVM memory.
How to stream larger files
The memory intensive operation can be avoided using our own custom code to parse the response from the SOAP web service.
The following example shows the SOAP message response with the attachments. This example is for Oracle UCM's GetFileByName operation.
The SOAP response message package is constructed using the
Java Mail API Problem
The SOAP web service client for downloading attachments we will be discussing uses the MimeMessage structure but we will avoid using the JAVA MAIL package as it is not efficient while downloading the contents. If you use MimeMessage java api to get the MimeBodyPart then you'll be in trouble as MimeMessage loads the entire content as byte array into memory for calculating the size and number of MimeBodyParts. So we will avoid using it for larger files if you have small JVM memory.
How to stream larger files
The memory intensive operation can be avoided using our own custom code to parse the response from the SOAP web service.
The following example shows the SOAP message response with the attachments. This example is for Oracle UCM's GetFileByName operation.
The SOAP response message package is constructed using the
Multipart/Related
media type. The structure of the response stream is as follows:- The primary SOAP message must be carried in the root body part of the Multipart/Related structure. Consequently the type parameter of the
Multipart/Related
media header will always equal theContent-Type
header for the primary SOAP 1.1 message, i.e.,text/xml.
- Referenced MIME parts must contain either a
Content-ID
MIME header.
Content-Type: multipart/related;
type="text/xml"; start="rootContent";
boundary="----=_Part_12_21424854.1424891476173"
SOAPAction:
"http://www.stellent.com/CheckIn/"
Content-Length: 1818
------=_Part_12_21424854.1424891476173
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-ID: rootContent
<soapenv:Envelope
xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:get=\"http://www.stellent.com/GetFile/\">
<soapenv:Header/>
<soapenv:Body>
<get:GetFileByName>
<get:dDocName>Test.txt</get:dDocName> <get:revisionSelectionMethod>LatestReleased</get:revisionSelectionMethod>
<get:rendition>primary</get:rendition>
<get:extraProps>
<get:property>
<get:name>soapResponseType</get:name>
<get:value>Multipart/Related</get:value>
</get:property>
</get:extraProps>
</get:GetFileByName>
</soapenv:Body>
</soapenv:Envelope>
------=_Part_12_21424854.1424891476173
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Content-ID: test.log
Hello
------=_Part_12_21424854.1424891476173--
As you can see above the response stream starts with boundary (------=_Part_12_21424854.1424891476173). Each MimeBodyParts are separated by boundary. The content of each MimeBodyPart starts after blank line. The blank line is used to seperate the headers and content of each MimeBodyPart. Using apache LineInputStream we read each line until we encounter the blank line for the attachment content. Once the blank line preceeding the attachment body is read we will switch back to BufferInputStream for efficiency. Don't forget to ignore the boundary line which indicates the end of response and exclude it from writing into the file.
|
The example was tested with 10 concurrent thread each downloaded 160MB of file from web service and the JVM memory utilization was mere 20MB.