3

画像を表示したいJSFページがあります。画像はblobとしてデータベースに保存されます。エンティティは次のようになります。

@Entity
public class Player
{
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long            id;
    @Lob
    private byte[]          pictureData;
    @Transient
    private StreamedContent streamedPicture;

    public StreamedContent getStreamedPicture()
    {
        if (streamedPicture == null && pictureData != null)
        {
            try
            {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                os.write(pictureData);
                streamedPicture = new DefaultStreamedContent(
                                                    new ByteArrayInputStream(
                                                                                os.toByteArray()),
                                                    "image/png");
            }
            catch (FileNotFoundException e)
            {}
            catch (IOException e)
            {}
        }
        return streamedPicture;
    }
}

JSFページは次のとおりです。

<!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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

<h:head></h:head>
<body>
    <ui:repeat var="player" value="#{playerbean.cachedPlayers}">
        <h:outputText value="#{player.id}" />
        <p:graphicImage value="#{player.streamedPicture}" rendered="#{player.streamedPicture != null}"/>
    </ui:repeat>
</body>
</html>

そして、私が呼ぶBeanは次のようになります。

@ManagedBean(name = "playerbean")
@SessionScoped
public class PlayerBean
        implements Serializable
{
    @EJB
    private PlayerManager   playerManager;
    private List<Player>    cachedPlayers;

    public List<Player> getCachedPlayers()
    {
        if (cachedPlayers == null)
        {
            cachedPlayers = playerManager.getAll();
        }
        return cachedPlayers;
    }
}

デバッグ中PrimeResourceHandlerに、メソッドにブレークポイントを設定しましたhandleResourceRequest()PrimeResourceHandler私が見ているコードにはこれが含まれています:

try {
    String dynamicContentEL = (String) session.get(dynamicContentId);
    ELContext eLContext = context.getELContext();
    ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class);
    StreamedContent content = (StreamedContent) ve.getValue(eLContext);
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();

    response.setContentType(content.getContentType());

    byte[] buffer = new byte[2048];

    int length;
    InputStream inputStream = content.getStream();
    while ((length = (inputStream.read(buffer))) >= 0) {
        response.getOutputStream().write(buffer, 0, length);
    }

    response.setStatus(200);
    response.getOutputStream().flush();
    context.responseComplete();

} catch(Exception e) {
    logger.log(Level.SEVERE, "Error in streaming dynamic resource.");
} finally {
    session.remove(dynamicContentId);
}

行を渡すと、StreamedContent content = (StreamedContent) ve.getValue(eLContext); contentnullのように見えます。もちろん、これによりNullPointerExceptionが発生します。ただし、JSFページで、値がnullの場合はレンダリングしないように要素に指示しました。

4

1 に答える 1

3

<p:graphicImage>コンポーネントはvalue、SessionScopedBean内の管理プロパティを指す属性を持つことはできません。値はRequestScopedBeanに設定する必要があります。

これは、image/jpegコンテンツタイプのHTTP応答に対するHTTP要求が本質的にステートレスであるためです。ブラウザはJSFページコンテンツの最初のリクエストを行い、次に<img>レンダリングされるすべてのHTMLタグに対して、動的に生成された各<img>タグのURLに個別のリクエストを行い、これらをフェッチします。ステートフルコンテキストで画像をフェッチすることは、実際には意味がありません。

于 2012-07-12T11:59:22.090 に答える