Hi Adnan,
I agree that Java records lack some flexibility but I think we can
achieve a nice layout. Here is a tentative design:
public interface PolarisEvent {
UUID id();
Instant timestamp();
PolarisPrincipal user();
static UUID createEventId() { return UUID.randomUUID(); }
}
Here is a typical event record:
public record BeforeSomethingEvent(
UUID id,
Instant timestamp,
PolarisPrincipal user,
String someOtherParameter)
implements PolarisEvent {}
And here is a typical event instantiation idiom:
@Inject SecurityContext securityContext;
@Inject Clock clock;
new BeforeSomethingEvent(
PolarisEvent.createEventId(),
clock.instant(),
(PolarisPrincipal) securityContext.getUserPrincipal(),
"someParameter");
What do you think of the above?
Thanks,
Alex
On Fri, Oct 24, 2025 at 10:15 AM Adnan Hemani
<[email protected]> wrote:
>
> Hi Alex,
>
> I had thought about this earlier and abandoned the idea due to implementation
> concerns. So, my question is how exactly will these methods be implemented
> and used?
>
> Let’s take id() as the talking point, but similar points can be applied to
> timestamp(). PolarisEvent is an interface and all implementations of this
> interface are Java records - as a result, neither PolarisEvent nor its
> implementations can contain non-static instance fields. So if a PolarisEvent
> cannot save its ID through a non-static instance field, how do we guarantee
> idempotency if id() is called twice on an instance of PolarisEvent?
>
> The other way I see is we instead include id, timestamp, and user as named
> arguments of every record signature along with a custom constructor which
> will generate the new ID and timestamp - which makes the code extremely messy
> IMO (and was one of the original reasons why we stuck to using an Interface
> for PolarisEvent rather than switching over to an ABC, which I had proposed
> earlier). Or we go towards using an intermediate ABC with PolarisEvent
> re-written as a Sealed Interface, with each record extending the intermediate
> ABC. I’m not sure I understand the ramifications of doing this yet, so cannot
> endorse this approach either.
>
> Did I miss some other way to make this work? Or were you thinking of
> something completely different?
>
> Best,
> Adnan Hemani
>
> > On Oct 23, 2025, at 10:18 AM, Alexandre Dutra <[email protected]> wrote:
> >
> > Hi all,
> >
> > Just to be clear, and sorry for the confusion: the idea was to add
> > those methods to the PolarisEvent interface, not PolarisEventListener.
> >
> > I agree with Mike that PolrisEventListener shouldn't deal with context
> > data. In my mind, each PolarisEvent instance would carry its own ID,
> > timestamp (at creation time) and user (the principal that triggered
> > the event).
> >
> > Thanks,
> > Alex
> >
> > On Thu, Oct 23, 2025 at 7:08 PM Michael Collado <[email protected]>
> > wrote:
> >>
> >> +1 on adding the described fields to the PolarisEvent.
> >>
> >> I don't think the PolarisEventListener is really the right place to add any
> >> default methods about context, though. I'm not sure if you meant adding
> >> those to the PolarisEvent interface so that existing records have a default
> >> value?
> >>
> >> Mike
> >>
> >> On Wed, Oct 22, 2025 at 10:26 PM Jean-Baptiste Onofré <[email protected]>
> >> wrote:
> >>
> >>> Hi Alex
> >>>
> >>> It makes sense to me.
> >>>
> >>> Are you also proposing to have default methods in the interface ?
> >>>
> >>> interface PolarisEventListener {
> >>>
> >>> default UUID id() { ... }
> >>>
> >>> default Instant timestamp() { ... }
> >>>
> >>> default PolarisPrincipal user() { ... }
> >>>
> >>> }
> >>>
> >>> Maybe we can have a default behavior that implementations can
> >>> "override" if needed.
> >>>
> >>> Regards
> >>> JB
> >>>
> >>> On Wed, Oct 22, 2025 at 5:08 PM Alexandre Dutra <[email protected]> wrote:
> >>>>
> >>>> Hi all,
> >>>>
> >>>> We have two (albeit incomplete) PolarisEventListener implementations
> >>>> today: one for JDBC and one for AWS CloudWatch.
> >>>>
> >>>> Both enhance event payloads internally by adding a timestamp and user
> >>>> data. These two attributes are indeed very common in event-oriented
> >>>> systems.
> >>>>
> >>>> The JDBC implementation also generates unique IDs internally. That's
> >>>> because the PolarisEvent interface lacks an id() method, despite the
> >>>> common need for event disambiguation.
> >>>>
> >>>> Therefore, I propose promoting these three attributes (ID, timestamp,
> >>>> user) to the PolarisEvent interface, by adding the following methods:
> >>>>
> >>>> UUID id();
> >>>> Instant timestamp();
> >>>> PolarisPrincipal user();
> >>>>
> >>>> This information is readily available at event instantiation sites,
> >>>> and can be provided via CDI injection without hassle.
> >>>>
> >>>> Let me know your thoughts.
> >>>>
> >>>> Thanks,
> >>>> Alex
> >>>
>