On Tue, Nov 25, 2025 at 8:20 AM Chris Colman <[email protected]> wrote:
> On 25/11/2025 4:28 pm, Martin Grigorov wrote: > > If you talk about Ajax requests you could solve that by using > > AjaxChannel.ACTIVE setting. The JavaScript logic will ignore any Ajax > > request in the same channel if there is an active request at the moment. > > I wish I knew about this earlier! Is this something that can be set via > a Wicket application config attribute or does it need to be done in raw > JavaScript somewhere? > See AjaxRequestAttributes ( https://github.com/apache/wicket/blob/999d205d3f27310bd657d20e86bd59ab1ed4d7f6/wicket-core/src/main/java/org/apache/wicket/ajax/attributes/AjaxRequestAttributes.java#L117 ) You could override it per Ajax behavior/component (#updateAjaxAttributes()) or globally with AjaxRequestTarget.IListener (see https://github.com/apache/wicket/blob/999d205d3f27310bd657d20e86bd59ab1ed4d7f6/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractDefaultAjaxBehavior.java#L149 and https://github.com/apache/wicket/blob/999d205d3f27310bd657d20e86bd59ab1ed4d7f6/wicket-core-tests/src/test/java/org/apache/wicket/ajax/GlobalUpdateAjaxAttributesTest.java#L42 ) > > To prevent multiple click processing we ended up creating an extension > to AjaxLink (could do the same with AjaxButton) called DebouncedAjaxLink > to act like a bit like a electronic debouncing circuit does to prevent > multiple inadvertent clicks being processed. > > Basically, instead of your derived class providing an onClick() impl you > provide a performAction() impl instead and while multiple clicks can > result in onClick() being invoked multiple times, performAction() will > only be called once. > > public abstract > class DebouncedAjaxLink<T> extends AjaxLink<T> > { > > private int semaphore = 0; > > ... > > /** > * Will only be called from onClick() if all other previous calls to > performAction have > * completed. > */ > public abstract void performAction(AjaxRequestTarget ajaxRequestTarget); > > > /** > * Handle any clicks, preventing multiple calls to performAction() > */ > public void onClick(AjaxRequestTarget ajaxRequestTarget) > { > synchronized (this) > { > > if (semaphore > 0) > { > // Preventing firing of action while last request is still > being processed > logger.warn("semaphore > 0"); > return; // ignore click > } > > semaphore++; // will be cleared after performAction invocation > returns > } > > try > { > performAction(ajaxRequestTarget); > } > finally > { > synchronized (this) > { > semaphore--; > } > } > } > > } > > Yes, it uses synchronized blocks but not really an issue in a web app > that most companies develop. > > Sync blocks are bad in a tight loop that has to do 10 million iterations > per second but are not really an issue for this UI/Web scenario unless > your app is running at Google scale - good problem to have ;) > > > > I guess you could reuse it for non-Ajax links by intercepting their click > > event. > > > > On Mon, 24 Nov 2025 at 10:55, Martijn Dashorst < > [email protected]> > > wrote: > > > >> In our application sometimes a user clicks double when a request takes > >> long, or they are using windows clicking behavior (double click). > >> > >> This is unfortunate as the server is processing the request twice, and > one > >> of them is discarded in the bit-void due to no browser listening for the > >> response... > >> > >> I know it is a bad idea to link request threads together, but... with > the > >> current pagelock mechanism we already do that in a sort of way. > >> > >> What if we were to keep a map of in progress (non-multipart for now) > >> requests parameters and the threads that are processing them, and when a > >> duplicate comes in for the same session, we subscribe to a future of the > >> original response, and respond with that to the browser? > >> > >> Martijn > >> >
