EN · DE · RU · FR · ES

#2787: FullCalendar.java

projectforge-wicket/src/main/java/net/ftlines/wicket/fullcalendar/FullCalendar.java Wicket Component (FullCalendar Main Class) · projectforge-wicket/src/main/java/net/ftlines/wicket/fullcalendar/FullCalendar.java 226 lines · 141 code · 37 comments · 48 blank
The concrete Wicket component that renders a FullCalendar JavaScript widget on a page and wires all server-side event handling. This is the orchestration center: it extends AbstractFullCalendar (header/assets) and implements IRequestListener (Ajax event fetching). On initialization, it generates random UUIDs for all event sources. Before each render, it sets up five callback behaviors (event fetch, click, drag-drop, resize, view change, date range select) if they haven't been configured externally. It renders the calendar's JSON configuration into a OnDomReadyHeaderItem, and delegates event requests to the GetEventsCallback behavior. Template methods (onEventDropped, onEventResized, etc.) provide default no-op implementations that subclasses or anonymous instances override.

Architecture

Lazy Callback Setup

The setupCallbacks() method is guarded by if (getEvents != null) return; — it runs exactly once per component lifecycle, in onBeforeRender(). For each callback type (events, click, select, drop, resize, view display), it checks the corresponding config field: if not already set externally, it creates a Wicket Ajax behavior and injects the generated handler script into the config model. This lazy pattern allows callers to either override the template methods (convenient for anonymous subclasses) or supply custom callback scripts via the config API (for advanced JavaScript integration).

Event Source UUID Assignment

On initialization, each event source gets a UUID generated by UUID.randomUUID() with non-alphanumeric characters stripped. This UUID serves as the source's identity for Ajax callbacks — it's embedded in the callback URL as part of the JavaScript function, and the server extracts it from the request to route events to the correct source.

Wicket 8 Migration: MicroMap → HashMap

The Wicket 8 upgrade removed org.apache.wicket.util.collections.MicroMap (a small-map optimization in older Wicket). The setupCallbacks() method was updated to use new HashMap<>() instead of new MicroMap<>() when passing the template URL variable. This was the only functional change to this class beyond copyright updates.

Event Handling Template Methods

Five protected methods provide hook points: onEventDropped, onEventResized (both return boolean indicating whether the change was accepted), onDateRangeSelected, onEventClicked, and onViewDisplayed. Default implementations do nothing. Subclasses override these to implement business logic — for example, persisting a dragged event's new timeslot in the database.

Ajax Concurrency

getAjaxConcurrency() returns AjaxConcurrency.QUEUE, ensuring that multiple rapid Ajax requests (e.g., from drag-and-drop operations) are processed sequentially rather than concurrently, preventing race conditions in event position updates.

JSON Configuration Rendering

The renderHead() method generates the FullCalendar initialization call: $("#markupId").fullCalendarExt({...serialized Config...});. It uses ToStringUtil.toJsonString(config) with the custom Joda-Time serializers from AbstractFullCalendar. The markup ID ties the JavaScript invocation to the specific DOM element.

Git History

CommitWhat changed
868d6abb7 through 916166996Six commits: five annual copyright header updates plus one functional change. The migration commit (0d183e5df) replaced MicroMap with HashMap in the setupCallbacks() method and added the corresponding java.util.HashMap/java.util.Map imports — a Wicket API compatibility fix required by the Wicket 8 upgrade that removed the MicroMap utility class. All other commits are copyright year increments.