Primefaces Показать изображение из базы данных

Я пытаюсь отобразить изображение клиента (хранится в CustomerMaster.customerPhoto в объекте BLOB). Я использую компонент imageBuilder (RequestScoped) для создания изображения на основе содержимого, хранящегося в CustomerMaster, которое доступно в клиентском компоненте (ViewScoped). Я добавил свойство в ImageBuilder для доступа к объекту CustomerMaster в компоненте клиента. Также добавлены операторы sysout для целей отслеживания.

Вот вывод

09:34:22,817 INFO  [stdout] (http--127.0.0.1-8080-2) getImage - 1
09:34:22,817 INFO  [stdout] (http--127.0.0.1-8080-2) getImage - 3
09:34:22,817 INFO  [stdout] (http--127.0.0.1-8080-2) getImage - 4
09:34:22,817 INFO  [stdout] (http--127.0.0.1-8080-2) getImage - 5PhotoMaster [photoId=1,  contentType=image/gif]    2064
09:34:22,817 INFO  [stdout] (http--127.0.0.1-8080-2) getImage - 6
09:34:22,827 WARNING [javax.enterprise.resource.webcontainer.jsf.context] (http--127.0.0.1-8080-2) JSF1091: No mime type could be found for file dynamiccontent.  To resolve this, add a mime-type mapping to the applications web.xml.
09:34:23,057 SEVERE [org.primefaces.application.PrimeResourceHandler] (http--127.0.0.1-8080-4) Error in streaming dynamic resource. Unable to set property customerBean for managed bean imageBuilderBean

Основываясь на операторах sysout, я вижу, что ImageBuilderBean может получить доступ к объекту CustomerMaster и создать DefaultStreamedContent.

Но позже я получаю следующее серьезное сообщение, и изображение не отображается на веб-странице:

09:34:23,057 SEVERE [org.primefaces.application.PrimeResourceHandler] (http--127.0.0.1-8080-4) Error in streaming dynamic resource. Unable to set property customerBean for managed bean imageBuilderBean

Если я использую Область сеанса в CustomerBean (вместо ViewScoped), все работает файл. Даже изображение отображается на веб-странице. Насколько я понимаю, не должно быть никаких проблем с вызовом компонента Viewscoped из компонента requestScoped.

Я не уверен, что не так. Пожалуйста помоги. См. код для справки.

ImageBuilder.Java

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

    @ManagedBean (name="imageBuilderBean")
    @RequestScoped
    public class ImageBuilderBean implements Serializable {

        private static final long serialVersionUID = -480089903900643650L;

        @ManagedProperty(value="#{customerBean}")    
        private CustomerBean customerBean;

        private StreamedContent image;

        public ImageBuilderBean() {
            super();
        }

        @PostConstruct
        void ResetBean(){
            System.out.println("getImage - 1");

            FacesContext context = FacesContext.getCurrentInstance();

            if (context.getRenderResponse()) {
                System.out.println("getImage - 2");
                // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
                image = new DefaultStreamedContent();
            }
            else {
                System.out.println("getImage - 3");

                CustomerMaster custMaster = customerBean.getCustMaster();
                if (custMaster != null){
                    System.out.println("getImage - 4");

                    PhotoMaster photo = custMaster.getCustomerPhoto();
                    if (photo != null) {

                        try {
                            System.out.println("getImage - 5" + photo + "    " + photo.getContent().length());
                            InputStream inputStream = photo.getContent().getBinaryStream();
                            image = new DefaultStreamedContent(inputStream, photo.getContentType());
                            System.out.println("getImage - 6");
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            System.out.println("exception Shirish");
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

Клиент.XHTML

<p:column>
    <p:graphicImage id="custImageId" value="#{imageBuilderBean.image}" cache="false" />
</p:column> 

CustomerBean.Java

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

@ManagedBean (name="customerBean")
@ViewScoped
public class CustomerBean implements Serializable {

private static final long serialVersionUID = -3727342589028832013L;
// Setters and Getters

Обновление:

Поскольку тег graphicImage преобразуется в тег <img> html. Браузер генерирует два запроса на отображение изображения. Генерируются следующие два URL-адреса:

  1. /proj/views/user/CustomerRegistration.xhtml — аннотации ManagedProperty возвращают клиентские компоненты с областью видимости.

  2. /proj/javax.faces.resource/dynamiccontent.xhtml — Не удалось вернуть customerBean. Следовательно, мы видим сообщение об ошибке «Невозможно установить свойство customerBean для управляемого компонента imageBuilderBean».

Какие-либо предложения?


person Shirish Bathe    schedule 05.11.2012    source источник
comment
У вас есть соответствующие геттеры/сеттеры для private StreamedContent image?   -  person Akos K    schedule 05.11.2012
comment
@akoskm: геттеры/сеттеры уже определены для обоих bean-компонентов.   -  person Shirish Bathe    schedule 05.11.2012
comment
Я использую URL-адрес данных ...   -  person Ekrem    schedule 19.10.2018


Ответы (1)


Проблема заключается в логике bean-компонентов ViewScoped и SessionScoped.

в bean-компонентах RequestScoped все запросы обрабатываются новым экземпляром bean-компонента
в bean-компонентах SessionScoped все запросы, содержащие один и тот же сеанс, обрабатываются одним и тем же экземпляром.

Bean-компоненты ViewScoped — это что-то среднее между этими двумя. он создает «псевдосессию», которая работает как в сеансовых компонентах, но извлекается другим способом. это не обрабатывается так же, как в bean-компонентах с областью сеанса, где браузер отправляет информацию о сеансе (например, в файле cookie или каким-либо другим способом), но он хранится на самой «веб-странице» (в javaScript), поэтому для каждого запроса ajax, отправляемого веб-страницей добавьте свой собственный «vievSessionKey» (уникальный для каждого представления).

При отображении страницы браузер отправляет запрос на веб-страницу, а затем браузер (не веб-страница) отправляет еще один запрос для каждой картинки. в этом случае запросы изображения не имеют viewSessionKey, сгенерированного во время запроса веб-страницы, поэтому bean-компоненты будут действовать, как другое, новое представление и инициализировать новый экземпляр bean-компонента.

если вы хотите выполнить такую ​​​​операцию с bean-компонентами ViewScoped, вам необходимо реализовать способ переноса данных между каждым новым экземпляром каждого bean-компонента. вы можете попробовать сделать какой-то менеджер Singleton, несущий данные изображения или некоторые статические поля. но это «уродливый» способ решения этой проблемы, и более логичным способом было бы сделать ваш сеанс bean-компонента ограниченным... или, по крайней мере, отделить некоторые функции от нового bean-компонента с областью сеанса.

ps: я знаю, что выкопал какую-то проблему с динозаврами, но у меня была такая же проблема, и, читая ваш вопрос, я понял логику того, что делается javascripts/браузером для каждого типа bean

person Misiakw    schedule 06.02.2013