Wicket
  1. Wicket
  2. WICKET-3757

Image always noncaching when included in ajax request. However, sometimes caching image is desirable.

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 1.5-RC4
    • Fix Version/s: 1.5-RC5
    • Component/s: wicket
    • Labels:

      Description

      On 1.5, Image's onComponentTag() performs this:

      if (AjaxRequestTarget.get() != null)

      { addAntiCacheParameter(tag); }

      The purpose here is to defeat browser's caching, However, sometimes the programmer has a unique URL to image and wishes the caching to occur, even for imags that are fetched by AJAX requests. An overridable method or property should be added to the Image class which controls whether the addAntiCacheParameter(tag) gets called. Perhaps something like defeatBrowserCache() with a javadoc that explains that for AJAX updates, the image's src attribute must be changed or browser will never fetch the image anew. Additionally, the method must be left as not final to allow subclasses to override it. Here's a suggestion:

      /**

      • The default behavior is to add wicket's anticaching url parameter
      • to every image fetched via AJAX request. This is because browsers
      • never examine their caches and fetch image data anew when
      • parts of the page is redrawn by an AJAX request.
        *
      • @param tag the component to be modified
        */
        protected void defeatBrowserCache(ComponentTag tag) {
        if (AjaxRequestTarget.get() != null) { addAntiCacheParameter(tag); }

        }

      And this method should be called on the last lines of Image#onComponentTag().

        Activity

        Antti S. Lankila created issue -
        Antti S. Lankila made changes -
        Field Original Value New Value
        Description On 1.5, Image's onComponentTag() performs this:

                        if (AjaxRequestTarget.get() != null)
                        {
                                addAntiCacheParameter(tag);
                        }

        The purpose here is to defeat browser's caching, obviously. However, this is done unconditionally, without any means to prevent the anticaching parameter from being added. The old split of Image vs. NonCachingImage was better, IMO. The reason is that when I show product images via an ajax panel, I give ResourceReference which uniquely identifies the image to be presented. This unique ID is in the URL, so there is no harm in caching the image -- in fact, it is highly desirable to improve response time and reduce server bandwidth usage.

        This use case is no longer supported, and the workaround is kludgy: you subclass Image and let superclass mangle the src and then anti-mangle it back, so I treat this as a regression from wicket 1.4. I would request that antiCacheParameter only be added to NonCachingImage (put it back like it was in wicket 1.4, which was more flexible and consistent). Alternatively, this current anticache parameter could be made smarter yet and only added when Image is constructed with Resource, but not added when it is constructed with ResourceReference. The thinking here is that a ResourceReference probably ought to always return some stable, named resource, whereas Resource may be dynamic or static.
        On 1.5, Image's onComponentTag() performs this:

                        if (AjaxRequestTarget.get() != null)
                        {
                                addAntiCacheParameter(tag);
                        }

        The purpose here is to defeat browser's caching, However, sometimes the programmer has a unique URL to image and wishes the caching to occur, even for imags that are fetched by AJAX requests. An overridable method or property should be added to the Image class which controls whether the addAntiCacheParameter(tag) gets called. Perhaps something like defeatBrowserCache() with a javadoc that explains that for AJAX updates, the image's src attribute must be changed or browser will never fetch the image anew. Additionally, the method must be left as not final to allow subclasses to override it. Here's a suggestion:

        /**
         * The default behavior is to add wicket's anticaching url parameter
         * to every image fetched via AJAX request. This is because browsers
         * never examine their caches and fetch image data anew when
         * parts of the page is redrawn by an AJAX request.
         *
         * @param tag the component to be modified
         */
        protected void defeatBrowserCache(ComponentTag tag) {
            if (AjaxRequestTarget.get() != null) {
              addAntiCacheParameter(tag);
            }
        }

        And this method should be called on the last lines of Image#onComponentTag().
        Antti S. Lankila made changes -
        Comment [ To better understand the way I encountered this issue: I have a single LightBoxPanel on page with multiple images, each which is enclosed in a link that shows the product image in the lightbox. The LightBoxPanel has a method setImage(), which controls the image to be displayed in the lightbox. When image is set, the component becomes visible and adjusts itself to present the image.

        To do this, setImage() first removes any existing Image from its html, and adds a new one:

        public void setImage(SomeBO x) {
          if (image != null) {
            getBodyContainer().remove(image);
          }
          add(image = new ByteArrayImage("image", x.getFileName(), x.getFileData()));
        }

        the constructor for ByteArrayImage which extends Image basically does just this:

        public ByteArrayImage(String id, String fileName, final byte[] fileData) {
          super(id, new ResourceReference(fileName) {
             public IResource getResource() {
                return new ByteArrayResource("image/jpeg", fileData);
             }
          });
        }

        The end result is that wicket renders an image URL like: <img src="wicket/resource/org.apache.wicket.application/fileName"/> and also finds some resource by that name. The URL arguably has too much gobbledygook in it, but at least it works like I want it to. Because ResourceReference's argument is a String, not a model, I was forced to remove the old image and add a new object instead. ]
        Martin Grigorov committed 1132923 (1 file)
        Reviews: none

        WICKET-3757 Image always noncaching when included in ajax request. However, sometimes caching image is desirable.

        Add #shouldAddAntiCacheParameter() which by default adds the parameter for Ajax requests.
        The user can override it and chnage the check with his own.

        Hide
        Martin Grigorov added a comment -

        With r1132923 the check whether to add the anti cache parameter is moved to overridable method org.apache.wicket.markup.html.image.Image.shouldAddAntiCacheParameter().

        Show
        Martin Grigorov added a comment - With r1132923 the check whether to add the anti cache parameter is moved to overridable method org.apache.wicket.markup.html.image.Image.shouldAddAntiCacheParameter().
        Martin Grigorov made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Assignee Martin Grigorov [ mgrigorov ]
        Fix Version/s 1.5-RC5 [ 12316423 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            Martin Grigorov
            Reporter:
            Antti S. Lankila
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 1h
              1h
              Remaining:
              Remaining Estimate - 1h
              1h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development