3

I am trying to display Customer Image (Stored in CustomerMaster.customerPhoto in BLOB object). I am using imageBuilder Bean (RequestScoped) to construct image based on contents stored in CustomerMaster which is available in Customer Bean(ViewScoped). I have added property in ImageBuilder to access CustomerMaster Object in customer Bean. Also added sysout statements for tracing purpose.

Here is output of

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

Based on sysout statements, I can see ImageBuilderBean is able to access CustomerMaster Object and able to create DefaultStreamedContent.

But Later on I am getting following severe message and image is not displyed on web page:

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

If I use Session scope in CustomerBean (instead of ViewScoped) everything is working file. Even Image is displayed on web page. As per my understanding there should not be any issues in calling Viewscoped bean from requestScoped Bean.

I am not sure what is wrong. Please help. Please see code for reference.

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();
                        }
                    }
                }
            }
        }

Customer.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

Update:

As graphicImage tag is converted to <img> html tag. Browser generates two requests to display image. Following two urls are generated:

  1. /proj/views/user/CustomerRegistration.xhtml - ManagedProperty annotations returns viewscoped customerBeans.

  2. /proj/javax.faces.resource/dynamiccontent.xhtml - Failed to return customerBean. Hence we are seeing "Unable to set property customerBean for managed bean imageBuilderBean" error message

Any suggestions?

Kevin Panko
  • 7,844
  • 19
  • 46
  • 58
Shirish Bathe
  • 597
  • 8
  • 18

1 Answers1

2

The problem is placed in the logic of ViewScoped and SessionScoped beans.

in RequestScoped beans all requests are dealed by new bean instance
in SessionScoped beans all requests that carry the same session are dealed by the same instance.

ViewScoped beans are something "between" those two. it creates "pseudo session" which work's like in session beans, but it's fetched other way. it's not dealed the same way as in session scoped beans where the browser sends session information (for example in cookie or in some other way) but it is keept in "webpage" itself (in javaScript) so for each ajax request send by webpage it add's it's own "vievSessionKey" (unique for each View).

While displaying page browser sends request for webpage and then the browser (not webpage) sends another request for each picture. in this case image requests don't have viewSessionKey generated while webpage request, so beans will act, as it is another, new View, and initialize new bean instance.

if you want to make such operation on ViewScoped beans you need to implement way of carrying data between each new instance of each bean. you can try to make some sort of Singleton manager carrying picture data or some static fields. but this is "ugly" way of solving this problem, and more logical way would be to make your bean session scoped... or at least separate some functionality to new session scoped bean.

ps: I know i dug out some dinosaur problem, but i was having the same problem and while reading your question i realised logic of what is done by javascripts/browser for each bean type

Misiakw
  • 840
  • 8
  • 27