Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » Trouble with images being cached (How to suppress image caching when using IImageField (or Icons in tables))
icon5.gif  Trouble with images being cached [message #991136] Mon, 17 December 2012 08:10 Go to previous message
Urs Beeli is currently offline Urs Beeli
Messages: 163
Registered: October 2012
Location: Bern, Switzerland
Senior Member
I have succesfully tried adding an image to a table page by following the description on Display_images_in_a_table_page howto. This works well for displaying "static" images in a table (I tried this on the company table page of the minicrm tutorial by just using a server side stored image whose name is identical to the company short name).

Next, I extended the CompanyForm to also display this image using an ImageField. This, too, worked nicely.

As a next step I added an image column to the person table page and added an ImageField to the PersonForm. Instead of using a "static" image I added the functionality to let the user choose an arbitrary image file to display (using a button from the company form) and then storing this image in the database (using a blob in a seperate table, accessed using the personNr). This, too, works in principle.

I soon noticed, that this works with the first image being set (either when a user adds an image for the first time or when first displaying an image from the DB after restarting the application). However, if I try to change the image assigned to a user, I started running into problems. The new data was being sent back to the database and stored, but both the ImageField in the form and the column in the table still displayed the old image.

After some debugging, I found out the following:
Both the icon in the table column and the ImageField use SwingIconLocator.getIcon() which in turn calls SwingIconLocator.getImage() to retrieve the image data. getImage() uses m_imagesByNameCache and as far as I could tell, there is no way to invalidate this cache from the client side.

I was using "Person-"+personNr as imageId on the client side (and the image cache described in the Howto linked above explicitely allows for udpating a caches image). However, the Swing client does not take this into account and keeps using the old image, that is cached in m_imagesByNameCache.

One solution would probably be for me to use a has over the image data as imageId to make sure the imageId/imageName changes with new content. However, over time this would make the swing side image cache contain tons of stale objects.

As I'm trying to learn as much about Swing as I can, I tried a different approach. I created a custom control that I named "UncachedImageField". In order to do this, I took the following steps:

In my scout client plugin I added the following files:

  • IUncachedImageField (a copy of IImagegeField)
  • IUncachedImageFieldUIFacade (a copy of IImageFieldUIFacade)
  • UncachedImageFieldEvent (a copy of ImageFieldEvent)
  • UncachedImagedFieldListener (a copy of ImageFieldListener)
  • AbstractUncachedImageField (a copy of AbstractImageField)

These files are 1:1 copies of the corresponding ImageField classes with the exception that they reference each other instead of the originals).

In my scout swing ui plugin I added the following files:

  • ISwingScoutUncachedImagedField (a copy of ISwingScoutImageField)
    This, too is a 1:1 copy of the original with adjusted references)
  • SwingScoutUncachedImageField (a copy of SwingScoutImageField with some modifications)
    - adjusting the names to the corresponding classes with "Uncached"
    - changing setImageFromScout as follows:
      protected void setImageFromScout(String imageId, Object image) {
        if (image == null) {
          if (imageId != null) {
            // try to use uncached image
            image = getUncachedIconLocator().getImage(imageId);
            if (image == null) {
              // as fallback, use cached image
              image = getSwingEnvironment().getImage(imageId);
            }
          }
        }
        getSwingImageViewer().setImage(image);
      }

    - added the following code to the class:
      private SwingUncachedIconLocator m_uncachedIconLocator;
      protected SwingUncachedIconLocator getUncachedIconLocator() {
        if (m_uncachedIconLocator == null) {
          m_uncachedIconLocator = new SwingUncachedIconLocator(getSwingEnvironment().getScoutSession().getIconLocator());
        }
        return m_uncachedIconLocator;
      }

  • SwingUncachedIconLocator (a copy of SwingIconLocator with some modifications)
      public Image getImage(String name) {
        if (name == null || AbstractIcons.Null.equals(name) || name.length() == 0) {
          return null;
        }
        Image img;
        synchronized (m_cacheLock) {
          //img = m_imagesByNameCache.get(name); // not using cache
          //if (img == null && !m_imagesByNameCache.containsKey(name)) { // not using cache
            img = createImageImpl(name);
            if (img == null) {
              img = autoCreateMissingImage(name);
            }
            //m_imagesByNameCache.put(name, img); // not using cache
            if (LOG.isDebugEnabled()) {
              LOG.debug("load image '" + name + "' as " + img);
            }
            if (img == null) {
              warnImageNotFound(name);
            }
          //} // not using cache
        }
        return img;
      }

  • added the following block to plugin.xml
         <formField
               active="true"
               modelClass="com.bsiag.minicrm.client.ui.form.fields.ext.IUncachedImageField"
               name="Uncached Image Field"
               scope="default">
            <uiClass
                  class="com.bsiag.minicrm.ui.swing.form.fields.ext.SwingScoutUncachedImageField">
            </uiClass>
         </formField>



I then changed the ImageField on my Form to be an UncachedImageField instead. With these changes the image on the Form is now updated whenever the user selects a different image. However, I have the feeling that there must be an easier solution to this...

Also, the image in the table column still uses the cached version of the icon locator and I haven't found out how to make that use the uncached icon locator.

So, my questions are:


  • what is the recommended way to handle images that can change during the life time of the client? Use constantly changing imageIds (bearing the cost of an overblown cache)? Or is there a more elegant solution I fail to see?
  • Instead of copying more than half a dozen files to emulate ImageField except for not using a cache in the icon locator, is there an easier way of changing the behaviour of a an existing FormField?
  • how would I need to proceed to make the table column icon use the uncached icon locator (if there is no easier solution to my problem)?


Thanks for any light you can shed on this issue.
 
Read Message icon5.gif
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic:P/Users, does not match outer scope rule
Next Topic:Max Fraction Digits stuck at 2
Goto Forum:
  


Current Time: Thu May 23 01:16:33 EDT 2013

Powered by FUDForum. Page generated in 0.02555 seconds