今日のは完全に自分向けのメモです(^^;
resource配下にないような(絶対パスでどこか指定フォルダから動的に読み込むような)画像ファイルを表示する際にPrimeFacesのgraphicImageを利用しています。その際にPrimeFacesで定義されたStreamedContentクラスを利用するのですが、こいつが結構ハマるポイントになってて、StackOverflowでも色々上がってます(^^;
普通にtry-with-resourcesを利用して書くと
StreamedContent file = null;
Path imagePath = Paths.get(filePath);
try(InputStream is = Files.newInputStream(imagePath, StandardOpenOption.READ)){
file = new DefaultStreamedContent(is, "image/jpeg", "hogehoge.jpeg");
}
こんな感じになりますが、これだと画像が表示されず、なんで…?となってました。
クローズ処理はPrimeFacesがよしなにやっているらしく、いきなりクローズすると駄目らしい…。
Should I close StreamedContent stream?
え、じゃあクローズを明示しないほうがいいの…?と以下のようなのを書いてしまうと
file = new DefaultStreamedContent(
Files.newInputStream(imagePath, StandardOpenOption.READ),
"image/jpeg", "hogehoge.jpeg");
無事に画像表示はされるのですが、画面表示が終わった後でもプロセスがファイルをつかんでしまっていました。
(今回、画像は定期入替でバッチが削除したりする流れなのですが、消せなかった)
これってPrimeFacesがちゃんとCloseしてないんじゃないの…!!とか思ったり(-_-;
余談:上記はクローズしてないのが明らかなので、わりと簡単に原因究明できますが、こういうコードがあちこちあったり、バッチプログラムがフォルダ操作したり…となると意外と原因究明が難しい気が(^^;
調べてたら「Process Explorer」なるツールがあって、これ使うと、例えば上記の画像が削除できない場合、掴んでいるプロセスが特定できたりして非常に便利でした。Windows専用ですが↓
http://technet.microsoft.com/ja-jp/sysinternals/bb896653.aspx
で、気持ちとしてはtry-with-resourcesを使いたく、ググってたらStackOverflowで同じようなことで悩んでた人が解決した方法がありました。
Primefaces is not immediately closing the stream of DefaultStreamedContent after read
読み込んだデータを一旦バイト配列に置いておいて、StreamedContentにはその配列からStreamを作って渡すという流れ(^^;
byte[] content = null;
try(InputStream is = Files.newInputStream(imagePath, StandardOpenOption.READ)){
content = IOUtils.toByteArray(is);
}
file = new DefaultStreamedContent(
new ByteArrayInputStream(content), "image/jpeg", "hogehoge.jpeg");
うーん、なんかイケてない…。