java ee 7 - How to use async servlet + non blocking IO for file download? -


my image files stored in database (i know shouldn't be, can't help). able render them on clients, i've implemented async servlet helps read binary stream off database column , write on output stream of servlet response. traditional io works fine here.

when thought of trying non blocking io async servlet (to test performance), binary data returned in response keeps getting corrupted.

starting oracle blog, i've seen various examples of file upload async nio servlet, no issue.

here's servlet code:

@webservlet(asyncsupported = true, urlpatterns = "/mydownloadservlet") public class fileretrievalservletasyncnio extends httpservlet {     private static final long serialversionuid = -6914766655133758332l;      @override     protected void service(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception     {         queue<byte[]> containerqueue = new linkedlist<byte[]>();          asynccontext asynccontext = request.startasync();         asynccontext.addlistener(new asynclistenerimpl());         asynccontext.settimeout(120000);          try         {             long attachmentid = long.valueof(request.getparameter("id"));             myattachmentdataobject retobj = servletutils.fetchattachmentheaders(attachmentid);              response = (httpservletresponse) asynccontext.getresponse();             response.setheader("content-length", string.valueof(retobj.getcontentlength()));             if (boolean.valueof(request.getparameter(servletconstants.req_param_enable_download)))                 response.setheader("content-disposition", "attachment; filename=" + retobj.getname());             response.setcontenttype(retobj.getcontenttype());             servletoutputstream sos = response.getoutputstream();             servletutils.fetchcontentstreaminchunks(attachmentid, containerqueue); // reads database , adds queue in chunks             sos.setwritelistener(new writelistenerimpl(sos, containerqueue, asynccontext));         }         catch (numberformatexception | ioexception exc)         {             exc.printstacktrace();             request.setattribute("message", "failed");         }     } } 

here's write listener implementation

public class writelistenerimpl implements writelistener {      private servletoutputstream output = null;     private queue<byte[]> queue = null;     private asynccontext asynccontext = null;     private httpservletrequest request = null;     private httpservletresponse response = null;      public writelistenerimpl(servletoutputstream sos, queue<byte[]> q, asynccontext actx)     {         output = sos;         queue = q;         asynccontext = actx;         request = (httpservletrequest) asynccontext.getrequest();     }      @override     public void onwritepossible() throws ioexception     {         while(output.isready())         {             while (!queue.isempty())             {                 byte[] temp = queue.poll();                 output.write(temp, 0, temp.length);             }              asynccontext.complete();             request.setattribute("message", "success");         }     }      @override     public void onerror(throwable t)     {         system.err.println(t);         try         {             response.senderror(httpservletresponse.sc_internal_server_error);         }         catch (ioexception exc)         {             exc.printstacktrace();         }         request.setattribute("message", "failure");         asynccontext.complete();     } } 

the response data looks this:

response data

what doing wrong?

not sure expect output in terms of async i/o should check output.isready() before every write. onwritepossible code should be:

while(output.isready() && !queue.isempty())  {        byte[] temp = queue.poll();        output.write(temp, 0, temp.length);  }   if (queue.isempty()) {       asynccontext.complete();       request.setattribute("message", "success");  } 

this allows onwritepossible() return if writing becomes blocked point of async i/o.

if write when writing blocked (output.isready() return false) different implementations may either ignore write or throw exception. either way output data either missing writes in middle or truncated.


Comments

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -