EN · DE · RU · FR · ES

#2790: AbstractAjaxCallbackWithClientsideRevert.java

projectforge-wicket/src/main/java/net/ftlines/wicket/fullcalendar/callback/AbstractAjaxCallbackWithClientsideRevert.java Abstract Wicket Behavior (FullCalendar Ajax with Revert) · projectforge-wicket/src/main/java/net/ftlines/wicket/fullcalendar/callback/AbstractAjaxCallbackWithClientsideRevert.java 82 lines · 35 code · 33 comments · 14 blank
An abstract Ajax callback behavior for FullCalendar interactions that need client-side revert on failure — specifically drag-and-drop and resize operations. When a user drags or resizes a calendar event, FullCalendar immediately moves/resizes the event in the UI and sends an Ajax callback to the server. If the server rejects the change (e.g., due to a scheduling conflict or business rule violation), this behavior sends a revert script back to the client that snaps the event to its original position. The mechanism uses a combination of Wicket Ajax call listeners (onSuccess/onFailure) and a jQuery data attribute to communicate the server's accept/reject decision to the client-side revert logic.

Architecture

Two-Phase Commit Protocol

FullCalendar implements optimistic UI updates: the event moves immediately on drag, and the server can accept (nothing changes) or reject (event reverts to original position). This class implements the server side of that protocol:

  1. On Ajax request, onEvent(AjaxRequestTarget) is called — the subclass implements business logic and returns true (accept) or false (reject)
  2. The result is stored in a jQuery data attribute on the document: $.data(document, '{uuid}', {boolean})
  3. On Ajax success, the success script reads the data attribute — if false, it executes the revert script (provided by the abstract getRevertScript() method)
  4. On Ajax failure (network error, server exception), the revert script always executes
  5. The data attribute is cleaned up after evaluation

UUID-Based State Channel

A random UUID (prefixed with "u") identifies the callback instance. This UUID is used as a jQuery data key to store the boolean result. This avoids global state collisions when multiple calendar instances or multiple callback types are on the same page. The UUID is generated once in the field initializer and persists for the behavior's lifetime.

Ajax Call Listener Integration

updateAjaxAttributes() is overridden to add two listeners:

Subclass Contract

Concrete subclasses must implement:

Git History

CommitWhat changed
868d6abb7 through ceb63e8a1Six annual copyright header updates. The two-phase commit protocol and UUID-based state channel have been stable — the mechanism correctly handles FullCalendar's optimistic update pattern and distinguishes between business rule rejections (server returns false) and infrastructure failures (Ajax error triggers unconditional revert).