Class EventCreatedListener

java.lang.Object
org.exoplatform.container.component.BaseComponentPlugin
org.exoplatform.services.listener.Listener<org.exoplatform.agenda.model.AgendaEventModification,Object>
org.exoplatform.caldav.listener.AgendaEventPropagationListener
org.exoplatform.caldav.listener.EventCreatedListener
All Implemented Interfaces:
org.exoplatform.container.component.ComponentPlugin, org.exoplatform.services.listener.ListenerBase<org.exoplatform.agenda.model.AgendaEventModification,Object>

public class EventCreatedListener extends AgendaEventPropagationListener
Puts a meeting into the calendars of the people invited to it, at the moment it is created rather than at the next background sweep.

Bound to exo.agenda.event.created, which nothing subscribed to. The three listeners this add-on registered all react to a meeting that already exists — it was edited, deleted, or answered — so the very first thing that happens to a meeting reached nothing at all. What made it look like a feature that worked is that editing it once, or answering it, fires updated or responseSaved and the copy appears; anyone testing by clicking around therefore saw it work.

Why this is not covered by the seeding pass

CaldavPendingInvitationService does seed pending invitations from the background sweep, so on a healthy instance most new meetings did eventually appear — minutes later, on the next sweep of that account. It is a safety net, not the path: it only looks at the upcoming window (60 days by default) and only at the first 200 meetings in it, so a meeting further out than that, or created in the past, was never copied by anything. This listener has no window at all, because it is told about exactly one meeting.

Only created, deliberately not poll.created

A date poll is broadcast under its own name and is spelled STATUS:TENTATIVE; it is not a scheduled meeting, and no copy of one is fanned out to the people invited to vote on it. The seeding path refuses it on its own (CaldavPendingInvitationService.seedOne requires CONFIRMED), but not subscribing is the honest way to say so.

Not subscribing is a statement about the fan-out, and it used not to be enough. The creator's own browser pushes their own copy of whatever they save, poll included (AgendaConnector.vue on agenda-event-saved, through CaldavPushRest into CaldavPushService.pushAgendaEvent), and every path afterwards kept that copy in step because it was a copy like any other — so a poll did reach a calendar, as a multi-day block spanning every option proposed. EXO-89863 ended that: CaldavPushService.pushAgendaEvent now refuses a poll in the private core every writer comes through, and existing poll copies are retired by the propagation service and by the mirror sweep. This listener is unchanged by it — refusing to subscribe to poll.created remains the honest way to say the fan-out has nothing to do here.

Why asynchronous, and why that is safe here

Same reason as EventUpdatedListener: agenda broadcasts this from inside the transaction that saves the event, and talking to one calendar server per attendee there would hold a database transaction open across as many network round trips. The kernel's RunListener establishes the container on that thread, which is what the base class checks for.

Being asynchronous is also what keeps a creation to one write per attendee. Agenda auto-accepts the organiser inside this very broadcast — its own AgendaReplyOnSaveListener is registered on created, runs synchronously, and makes agenda emit responseSaved, which this add-on also listens to. Both listeners are asynchronous and the kernel's listener executor is a single thread, so they run one after the other in the order they were queued, and neither ordering writes twice: the answer path refuses when the meeting has no copy yet, and the seeding path refuses when it already has one.

The writer that is not on that thread is the author's own browser, which pushes their copy on save. That one races, and it is why CaldavEventPropagationService.propagateCreation(long, long) is told who the author is and skips them — see its javadoc for what that costs.

Glue only, per the extensibility norm: every decision about who receives a copy and what it says is taken in CaldavEventPropagationService.

  • Field Summary

    Fields inherited from class org.exoplatform.container.component.BaseComponentPlugin

    desc, name
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    protected void
    propagate(CaldavEventPropagationService propagationService, org.exoplatform.agenda.model.AgendaEventModification modification)
    Asks for the new meeting to be copied into the calendar of everybody invited to it who accepts copies.

    Methods inherited from class org.exoplatform.caldav.listener.AgendaEventPropagationListener

    onEvent, setCaldavEventPropagationService

    Methods inherited from class org.exoplatform.container.component.BaseComponentPlugin

    getDescription, getName, setDescription, setName

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface org.exoplatform.services.listener.ListenerBase

    getName
  • Constructor Details

    • EventCreatedListener

      public EventCreatedListener()
  • Method Details

    • propagate

      protected void propagate(CaldavEventPropagationService propagationService, org.exoplatform.agenda.model.AgendaEventModification modification)
      Asks for the new meeting to be copied into the calendar of everybody invited to it who accepts copies.

      The modifier is handed over as well, because a creation names its author and the author's own copy is written by their browser rather than here. The service is what decides that; this only carries what the broadcast said.

      Specified by:
      propagate in class AgendaEventPropagationListener
      Parameters:
      propagationService - the resolved service
      modification - the modification agenda broadcast