I have to send a binary stream of a blob by means of a ServletOutputStream.
I'm using the following technologies and software: Oracle 11, WebSphere 7, Springframework 2.5.5, Hibernate 3.3.SP1.
There are two Oracle databases. The first one contains tables for description of documents I have to transfer, and the second one - content of the documents.
I also have configured support for XA datasources in WebSphere and JtaTransactionManager in spring.
I obtain a reference to a document and content itself in one transaction.
JDBC specification tells us that LOBs are transactional objects and portable applications should use such objects within transactions.
And I have the following questions:
@Transactional
public InputStream getContent(Long docId) {
Blob blob = getBlob(...);
return blob.getBinaryStream();
}
public ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) {
Long docId = ServlerRequestUtils.getRequiredLongParameter(req);
InputStream is = service.getContent(docId);
copy(is, resp.getOutputStream());
return null;
}
If it is not legal how to transfer BLOB's binary stream to the end user if the content of the BLOB is large enough and there is preconfigured transaction timeout in the application server? Do I have to handle transactions manually and set the timeout to zero (transaction never time out)?
What is the best way to transfer BLOB's binary stream to the end user in such a case?
You're right in that returning's the BLOB's stream out of your tx method is not a good idea... it might work under certain circumstances, database depending, but it's risky.
The solution is to turn the problem inside out. Pass the servlet's OutputStream
in to your transactional method. This avoid the transaction issue, and keeps your stream handling in one place:
@Transactional
public void getContent(Long docId, OutputStream outputStream) {
Blob blob = getBlob(...);
InputStream blobStream = blob.getBinaryStream();
copy(blobStream, outputStream);
blobStream.close(); // ignoring the usual stream closing try/catch stuff for brevity
}
public ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) {
Long docId = ServlerRequestUtils.getRequiredLongParameter(req);
service.getContent(docId, resp.getOutputStream());
return null;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With