[ 
https://issues.apache.org/jira/browse/WICKET-6055?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15071011#comment-15071011
 ] 

ASF GitHub Bot commented on WICKET-6055:
----------------------------------------

Github user martin-g commented on a diff in the pull request:

    https://github.com/apache/wicket/pull/151#discussion_r48414689
  
    --- Diff: 
wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxLazyLoadPanel.java
 ---
    @@ -139,56 +182,176 @@ protected void handleCallbackScript(final 
IHeaderResponse response,
        @Override
        protected void onBeforeRender()
        {
    -           if (state == 0)
    +           if (state == LoadingState.WAITING_FOR_LAZY_COMPONENT)
                {
                        add(getLoadingComponent(LAZY_LOAD_COMPONENT_ID));
    -                   setState((byte)1);
    +                   setState(LoadingState.REPLACING_LAZY_COMPONENT);
                }
                super.onBeforeRender();
        }
     
    +   @Override
    +   public void onEvent(IEvent<?> event)
    +   {
    +           super.onEvent(event);
    +
    +           if (state == LoadingState.REPLACING_LAZY_COMPONENT)
    +           {
    +                   if (isReadyForReplacement())
    +                   {
    +                           // create the lazy load component
    +                           Component component = 
getLazyLoadComponent(LAZY_LOAD_COMPONENT_ID);
    +
    +                           // replace the spinner with the new component
    +                           AjaxLazyLoadPanel.this.replace(component);
    +
    +                           // mark replacement as done
    +                           setState(LoadingState.REPLACEMENT_COMPLETED);
    +
    +                           // remove ourselves from the timer
    +                           getLazyLoadTimer().removeLazyLoadPanel(this);
    +
    +                           AjaxRequestTarget target = 
getRequestCycle().find(AjaxRequestTarget.class);
    +
    +                           // notify our subclasses of the updated 
component
    +                           onComponentLoaded(component, target);
    +
    +                           // repaint our selves if there's an AJAX 
request in play, otherwise let the page
    +                           // redraw itself
    +                           if (target != null)
    +                           {
    +                                   target.add(AjaxLazyLoadPanel.this);
    +                           }
    +                   }
    +           }
    +   }
    +
    +   @Override
    +   protected void onRemove()
    +   {
    +           super.onRemove();
    +
    +           // mark replacement as done
    +           setState(LoadingState.REPLACEMENT_COMPLETED);
    +
    +           // remove ourselves from the timer
    +           AjaxLazyLoadTimer timer = getLazyLoadTimer();
    +           if (timer != null)
    +           {
    +                   timer.removeLazyLoadPanel(this);
    +           }
    +   }
    +
        /**
    +    * Sets the new LoadingState for this panel.
         * 
    -    * @param state
    +    * @param newState
         */
    -   private void setState(final byte state)
    +   private void setState(final LoadingState newState)
        {
    -           this.state = state;
    +           this.state = newState;
                getPage().dirty();
        }
     
        /**
    +    * Gets the central lazy load timer from the page if one is registered
         * 
    -    * @param markupId
    -    *            The components markupid.
    -    * @return The component that must be lazy created. You may call 
setRenderBodyOnly(true) on this
    -    *         component if you need the body only.
    +    * @return the central lazy load timer or {@code null}
         */
    -   public abstract Component getLazyLoadComponent(String markupId);
    +   private AjaxLazyLoadTimer getLazyLoadTimer()
    +   {
    +           return getPage().getMetaData(AJAX_LAZY_LOAD_TIMER);
    +   }
     
        /**
    -    * Called when the placeholder component is replaced with the lazy 
loaded one.
    -    *
    -    * @param component
    -    *      The lazy loaded component
    -    * @param target
    -    *      The Ajax request handler
    +    * Sets the central lazy load timer on the page
    +    * 
    +    * @param timer
    +    *            the timer to set
         */
    -   protected void onComponentLoaded(Component component, AjaxRequestTarget 
target)
    +   private void setLazyLoadTimer(AjaxLazyLoadTimer timer)
        {
    +           getPage().setMetaData(AJAX_LAZY_LOAD_TIMER, timer);
        }
     
        /**
    -    * @param markupId
    -    *            The components markupid.
    -    * @return The component to show while the real component is being 
created.
    +    * @deprecated No longer called as the AjaxLazyLoadPanel uses a central 
AJAX timer, and it
    +    *             doesn't make sense to modify the single timer from 
multiple panels
         */
    -   public Component getLoadingComponent(final String markupId)
    +   @SuppressWarnings("javadoc")
    +   @Deprecated
    +   protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
        {
    -           IRequestHandler handler = new ResourceReferenceRequestHandler(
    -                   AbstractDefaultAjaxBehavior.INDICATOR);
    -           return new Label(markupId, "<img alt=\"Loading...\" src=\"" +
    -                   RequestCycle.get().urlFor(handler) + 
"\"/>").setEscapeModelStrings(false);
        }
     
    +   /**
    +    * Allows subclasses to change the callback script if needed.
    +    * 
    +    * @param response
    +    *            the current response that writes to the header
    +    * @param callbackScript
    +    *            the JavaScript to write in the header
    +    * @param component
    +    *            the component which produced the callback script
    +    */
    +   protected void handleCallbackScript(final IHeaderResponse response,
    +           final CharSequence callbackScript, final Component component)
    +   {
    +           response.render(OnDomReadyHeaderItem.forScript(callbackScript));
    +   }
    +
    +   /**
    +    * The AJAX timer for updating the AjaxLazyLoadPanel. Is designed to be 
a page-local singleton
    +    * keeping track of multiple LazyLoadPanels using reference counting.
    +    */
    +   private static class AjaxLazyLoadTimer extends AbstractAjaxTimerBehavior
    +   {
    +           private static final long serialVersionUID = 1L;
    +
    +           private final List<AjaxLazyLoadPanel> lazyLoadPanels = new 
ArrayList<>();
    +
    +           public AjaxLazyLoadTimer()
    +           {
    +                   super(Duration.ONE_SECOND);
    --- End diff --
    
    +1 to make the duration configurable, e.g. overridable method in 
AjaxLazyLoadPanel.


> AjaxLazyLoadPanel should provide non-blocking lazy load
> -------------------------------------------------------
>
>                 Key: WICKET-6055
>                 URL: https://issues.apache.org/jira/browse/WICKET-6055
>             Project: Wicket
>          Issue Type: Improvement
>          Components: wicket-extensions
>    Affects Versions: 7.1.0
>            Reporter: Martijn Dashorst
>            Assignee: Martijn Dashorst
>
> When having multiple AjaxLazyLoadPanels on your page, they all block their 
> Wicket request thread until the content is ready to load. This can be 
> problematic when you try to wait for some background job to finish and want 
> to poll for that job to be ready, and only then update the contents.
> The improvement would be to add a method that gives the developer the option 
> to not update just yet (isReadyForReplacement) and when it returns true, 
> start the replacement. By default this would return true, implementing the 
> current behavior of the AjaxLazyLoadPanel.
> Furthermore to improve the responsiveness of the ALLP it should add a single 
> timer to the page that can be used by multiple ALLPs to update themselves. 
> The timer would poll each second and the ALLPs would use Wicket's event bus 
> to update themselves. With some reference counting, the timer can remove 
> itself from the page when all ALLPs have updated themselves.
> This enables refreshing the page as well when outside an AJAX context, or 
> having a user be impatient and pressing F5.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to