StepTNT
StepTNT

Reputation: 3967

Showing a dynamic image that depends on a Request Parameter

I'm trying to build a user profile page to show some details about my users.

The url of the page is something like profile.xhtml?username=randomString.

So, what I've to do is loading all the data of randomString's user.

It goes everything fine since it's the moment to show user's image.

I'm using PrimeFaces with graphicImage component, but the problem is that it causes a NEW request to get the image, so the request parameter is actually lost and the getAvatar() method receives a null parameter.

One solution may be making the bean SessionScoped, but it will take data from the first requested user and it will show them even if randomString will change, so I'm asking for help :

How can I show a dynamic image from database that depends on a request parameter?

Thanks :)

EDIT : New code following BalusC's reply

JSF Page :

<c:set value="#{request.getParameter('user')}" var="requestedUser"/>                    
<c:set value="#{(requestedUser==null) ? loginBean.utente : userDataBean.findUtente(request.getParameter('user'))}" var="utente"/>
<c:set value="#{utente.equals(loginBean.utente)}" var="isMyProfile"/>
<pou:graphicImage value="#{userDataBean.avatar}">
    <f:param name="username" value="#{utente.username}"/>
</pou:graphicImage>

(I'm using this vars because I want the logged user's profile to be shown if page request il just profile.xhtml without parameters)

Managed Bean :

@ManagedBean
@ApplicationScoped
public class UserDataBean {

    @EJB
    private UserManagerLocal userManager;

    /**
     * Creates a new instance of UserDataBean
     */
    public UserDataBean() {
    }

    public Utente findUtente(String username) {
        return userManager.getUtente(username);
    }

    public StreamedContent getAvatar(){
        String username = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("username");
        System.out.println(username==null);
        Utente u = findUtente(username);
        return new DefaultStreamedContent(new ByteArrayInputStream(u.getFoto()));
    }
}

What's wrong with it? username is always null!

EDIT 2 : Added reply to BalusC

Yeah, because the getAvatar() method calls findUser() as I need to find the user's entity with the username passed as parameter (<f:param> won't allow me to pass an object!).

So findUser() throws an exception because I'm using entityManager.find() with a null primary key!

Btw, I'm absolutely sure that both #{utente} and #{utente.username} are not null because the panel that contains the image is rendered only if #{utente ne null} and username is its primary key!

So I can't really check the HTML output!

I'm afraid that #{utente} is lost when I call getAvatar() as getting an Image requires a new http request

Upvotes: 2

Views: 9820

Answers (1)

BalusC
BalusC

Reputation: 1108722

Pass it as <f:param>. It will be added during render response.

<p:graphicImage value="#{images.image}">
    <f:param name="id" value="#{someBean.imageId}" />
</p:graphicImage>

The #{images} helper bean can just look like this:

@ManagedBean
@ApplicationScoped
public class Images {

    @EJB
    private ImageService service;

    public StreamedContent getImage() throws IOException {
        FacesContext context = FacesContext.getCurrentInstance();

        if (context.getRenderResponse()) {
            // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL.
            return new DefaultStreamedContent();
        }
        else {
            // So, browser is requesting the image. Get ID value from actual request param.
            String id = context.getExternalContext().getRequestParameterMap().get("id");
            Image image = service.find(Long.valueOf(id));
            return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
        }
    }

}

As the above helper bean has no request based state, it can safely be application scoped.

Upvotes: 7

Related Questions