Wicket 8.2.0 までは、Wicket RequestCycle
即ち、WebPage上で getRequestCycle().getResponse()
で取得する org.apache.wicket.request.Responseから
取得する OutputStream に書き込むことで、
HTML でないものをレスポンス応答することに問題は発生しなかった。
しかし、Wicket 8.3.0 以上のバージョンでは、
以下のように、JPEG画像を返す WebPage として構築すると、、
flower.jpg を resouce上に置いたとして、
String classesPath = ((WebApplication)getApplication()).getServletContext().getRealPath("WEB-INF/classes"); File imagefile = new File(classesPath + "/img/flower.jpg");
OutputStream を RequestCycle から getResponse を介して取得して、
WebResponse webresponse = (WebResponse)getRequestCycle().getResponse(); webresponse.setContentType("image/jpeg"); try(InputStream in = new FileInputStream(imagefile)){ OutputStream out = getRequestCycle().getResponse().getOutputStream(); in.transferTo(out); out.flush(); }catch(Exception ex){ logger.error(ex.getMessage(), ex); }
このように画像を送ると、
重大: サーブレット [default] のServlet.service()が例外を投げました
java.lang.IllegalStateException: レスポンスがコミットされた後でsendError()を呼び出すことはできません
となってしまう。
Wicket 8.3.0 以降 WebFilter の処理が変わったことを示しており、
このように直接 RequestCycle から取得する OutputStream に出力したのでは順序が遅いようだ。
解決策、、、
Wicket 8.3.0~ 以降では、、
RequestCycle の scheduleRequestHandlerAfterCurrent を使用して
org.apache.wicket.request.IRequestHandler の
respond(IRequestCycle requestCycle)
ラムダ式で、IRequestCycle 即ち、RequestCycle から取得する OutputStreamで出力するようにする。
上の imagefile 出力は、以下のように書く。
getRequestCycle().scheduleRequestHandlerAfterCurrent(c->{ WebResponse ws = (WebResponse)c.getResponse(); ws.setContentType("image/jpeg"); try(InputStream in = new FileInputStream(imagefile)){ OutputStream out = c.getResponse().getOutputStream(); in.transferTo(out); out.flush(); }catch(Exception ex){ logger.error(ex.getMessage(), ex); } });
Wicket 8.3.0 から、こう書かないとダメだ。