Image refresh not working

Hi,
I have implemented a class that extends a VerticlLayout that display an Image component.
I use a button “upload” to select (on file system) the image to load and display.

The first time I select an image to laod, it’s working fine.
But if I want to change (update) the image, it’s not refreshing the image automatically.
To see the new Image, I must navigate to another page of my application or do a refresh of the page !!!

In the Vaadin book, I have checked the example for

Generating and Reloading Images

and implemented it the same way but it still not working !!!

Below, a part of my code :

// SOME PROPERTIES OF MY CLASS THAT EXTENDS VERTICAL LAYOUT
    private Image            picture  = new Image();
    private byte             bytePicture;
    private StreamResource   pictureResource;


// CONSTRUCTOR
public UploadLogo() {
     setImmediate(true);
     initPicture();
     ...
     addComponent(picture);
}

    // CALLED FROM CONSTRUCTOR
    private void initPicture() {
        picture.setCaption("Picture: ");
        picture.setImmediate(true);

        // reportConfig STORE THE PICTURE IN DB
        if (reportConfig != null) {
            bytePicture = reportConfig.getPicture();
            StreamResource.StreamSource pictureSource = new StreamResource.StreamSource() {

                @Override
                public InputStream getStream() {
                    // return the byte[] from the EafrdReportConfiguration object.
                    return new ByteArrayInputStream(bytePicture);
                }
            };

            pictureResource = new StreamResource(pictureSource, reportConfig.getFileName());
            pictureResource.setCacheTime(0);

            //picture.setSource((Resource) pictureResource);
            picture = new Image(null, pictureResource);
        }
    }

// A LISTENER METHOD USED WHEN THE IMAGE HAVE BEEN LOADED
// THE REFRESH SHOULD WORK HERE !!!
    @Override
    @ListenerMethod
    public void uploadEnded(UploadEndEvent event) {
        final String[] fileParams = (event.getFileName()).split("\\.");
        final String fileName = fileParams[0]
;
        final long fileSize = event.getFileSize();
        final String mimeType = event.getMimeType();
        final String fileExt = fileParams[1]
;

        picture.markAsDirty();

        if (isFileAccepted(fileSize, mimeType)) {//recheck file size and mime type
            // Get the selected picture.
            final byte[] binaryPic = event.getByteArrayOutputStream().toByteArray();
            // ADD A TIMESTAMP TO THE NAME OF THE FILE
String filename = makeFileName(fileExt, fileName);

            reportConfig.setPicture(binaryPic);
            reportConfig.setFileName(filename);
            pictureResource.setFilename(filename);


            // Save it to the DB.
            ...

            // If saved ok, we display a notification to the user.
            if (saved) {
                fileNameField.setValue(filename);
                Notification.show("Picture saved", Type.HUMANIZED_MESSAGE);
            }
        }
    }

I already spent 1 1/2 day on this issue.
Please help me :wink:

Thank you.

bytePicture is a array of byte.
I don’t know how I did the copy / paste without the “” ?
The declaration of this property is :

private byte[] bytePicture;

Ok, I’ve find a solution to my problem :slight_smile:

In my first post (
see above
) after the line 62 of the source code, I have added the lines below.

            // lines added at line 62 in the code above
            StreamResource.StreamSource pictureSource = new MSLogoSource(binaryPic);
            pictureResource.setFilename(filename);
            pictureResource.setStreamSource(pictureSource);
            picture.setSource(pictureResource);

I will add the source of the class MSLogoSource below.

Now, I will try to explain how it’s working in a minimum of lines

In the
code above
, the
constructor
of the class do a call to the private method

initPicture()

.


initPicture()

get the image stored in the DB as a
byte[]

, by calling

reportConfig.getPicture();

at line
22
where

reportConfig

is a domain object used to store the selected picture. (
You don’t have to care about this class, it’s just to explain the idea of the system that I have implemented and to explain from where the image is coming
.)

  • This
    byte[]


    bytePicture
    is used to create a
    StreamSource
    pictureSource

    .
  • The

    pictureSource

    is used to create a
    StreamResource


    pictureResource

    .
  • The

    pictureResource

    is used to create the
    Image


    picture

    .

After

initPicture()

, the constructor add the

picture

to the Layout.
So far, it was ok, the problem start when a user try to change the picture present on screen.

Each time a user upload a new
Image
(to change / update the old one), the listener method


uploadEnded(UploadEndEvent event)

is called and the
Image
is
refreshed using the four lines added at line 62
.

MSLogoSource:

public class MSLogoSource implements StreamResource.StreamSource {

    private byte[]    bytePicture;

    /**
     *
     */
    public MSLogoSource(byte[] bytePicture) {
        this.bytePicture = bytePicture;
    }

    @Override
    public InputStream getStream() {
        return new ByteArrayInputStream(bytePicture);
    }
}

Excellent. I wondered about it a bit yesterday, but couldn’t see an obvious problem, although not all code was shown. Anyhow there’s the
book example with a memory buffer
for uploading images and it works.