4

I am trying to display a which is stored in a database. I have a <o:graphicImage value="#{image.getById(1)}" />.

Note: The ID (1) is only for testing.

My property looks like:

@Lob
private byte[] image;

and my dao/service is this:

@Name
@ApplicationScoped
public class Images {

    @Inject
    private UserDAO userDAO;

    public byte[] getById(int id) {
        return userDAO.getUserByID(id).getImage();
    }

To the concrete problem:

I just implemented this and the image is displayed correctly. I set the image manually to NULL in the database.

My assumption: The image is not found and the image is not displayed (or the typical 'image is not found'-image.).

But: The old image is displayed. Even after a restart of the server and a clean. Nothing changed. I tried to upload an other image to the database - same result.

What is the problem here? Where is my fault? How can I fix this?

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
alexander
  • 999
  • 2
  • 15
  • 34

1 Answers1

5

The image is being cached by the client. The <o:graphicImage> is very effective in this.

You basically need to clean the browser cache, or to perform a forced reload in browser, or open an incognito window.

One way to avoid this is to include the image's "last modified" timestamp in the lastModified attribute, which can be either a java.util.Date, or a java.lang.Long representing the epoch time. Best is to add this property to your entity.

<o:graphicImage ... lastModified="#{image.lastModified}" />

It will ultimately end up as v= request parameter in the generated image URL, hereby tricking the browser cache when it changes.

Another way is to just change image's ID in method argument. It's in that perspective also a bit strange if you still keep providing the old image ID in the HTML response while this ID doesn't exist in the database anymore.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • Are there any other possible ways to avoid this? Should I set the `lastModified` after saving/updating the image? – alexander May 09 '15 at 18:01
  • I'm not sure why you would "avoid" this. This is bad practice wrt performance. You could always hack around with `lastModified="#{startup.time}"` so that a server restart is sufficient to change it (like done on OF showcase because it merely uses stub data and not real DB data). And yes, just set it during `@PrePersist` and `@PreUpdate` (assuming JPA). – BalusC May 09 '15 at 18:02
  • I don't really get it why `lastModified` is necassary here. Why is ` not recognizing the update? I want avoid this, because it's for me not quite sure why it is exactly nessacary. – alexander May 09 '15 at 19:00
  • 1
    How when where should `` know the image has changed? It should then also know which 'version' the user originally requested. You, the developer, are the only one that can store somewhere when the image changes. Save that date e.g. in the database with the image and set it as the value of the `lastModified` attibute – Kukeltje May 09 '15 at 20:03
  • Indeed. It's actually not different from "regular" images in public webcontent folder via ``, when you change it, it also won't be reflected in client unless you perform a forced reload. Only the `` allows an easier way to provide the "image version" along via `lastModified` attribute, so that the enduser never needs to perform a forced reload. – BalusC May 10 '15 at 06:17
  • Moreover, if the image doesn't exist anymore in database, then you would also not specify its ID in the method, right? – BalusC May 10 '15 at 06:26
  • It is an interesting topic so far. Thank you @BalusC for your suggestion. I will test it now. Last question: What exactly do you mean with "forced reload"? I did a reload with F5 and CTRL + R (I guess this is not a forced reload, because it didn't work.) – alexander May 10 '15 at 09:04
  • Use Ctrl+F5 or disable cache (when using Chrome, under Network tab in webdeveloper toolset (F12)). Or just spawn an incognito window (Ctrl+Shift+N). – BalusC May 10 '15 at 09:48
  • I implemented this stuff. It did not work. I checked all stuff and was shortly before to response here. Finally it comes to my mind: "Where is `lastModified`? Well, it works like a charme. I get it, why `` does not recognize the update/delete of the image. But why is a `@ApplicationScoped` Bean necessary here? Is there not a simple way with a `@RequestScoped` Bean? – alexander May 11 '15 at 06:56
  • To force the "noob" developer that the bean is stateless (like a normal servlet), otherwise the developer would try or infer things which are technically wrong. – BalusC May 11 '15 at 07:06