PrimeFaces GraphicImage と StreamedContent を使う時のメモ

ユーザーガイドに載ってる内容も込みで。

  • StreamedContent に ViewScoped は使えない。
  • RequestScoped にした場合、リクエストが2回来るから f:param で識別子を渡して getter で StreamedContent を生成し返すこと。

html 的には、<img src="..." > になるので commandButton等 の actionListener で StreamedContent を生成しても、<img src="..."> で画像を取りに行くリクエストではインスタンスが存在しない。

GraphicImage で使う場合は、field に StreamdContent を持つより、単に getter だけ用意した方が良さげな気がする。
画面的に ViewScoped を使いたい場合は、BackingBean を分ける事で実現可能。
コード例は Xtend で。

import java.io.File
import java.io.Serializable
import java.nio.file.Files
import java.nio.file.StandardOpenOption
import javax.enterprise.context.RequestScoped
import javax.inject.Named
import org.primefaces.model.DefaultStreamedContent
import org.primefaces.model.StreamedContent
import javax.faces.context.FacesContext
import javax.faces.view.ViewScoped
@ViewScoped
@Named
class BackingBean implements Serializable {
  @Property String fileNm
  def void submit() {}
}
@RequestScoped
@Named
class ImageBackingBean {
  def StreamedContent getImage() {
    val param = FacesContext.currentInstance
      .externalContext.requestParameterMap.get("name")
    val fileNm = if (param.nullOrEmpty) "default.png" else param
    new DefaultStreamedContent(
      Files.newInputStream(
        Paths.get("c:/work/image", fileNm), StandardOpenOption.READ))
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
  <title>テスト</title>
</h:head>
<h:body>
  <h:form id="form">
    <p:inputText value="#{backingBean.fileNm}"/>
    <p:graphicImage value="#{imageBackingBean.image}" >
      <f:param name="name" value="#{backingBean.fileNm}"/>
    </p:graphicImage>
    <p:commandButton actionListener="#{backingBean.submit}" value="サブミット" ajax="false"/>
  </h:form>
</h:body>
</html>