Hi all, I am going to assume that we have reached a consensus on this topic and I will start working on it.
If someone disagrees, please chime in. Thanks, Alex Thanks, Alex On Sun, Oct 26, 2025 at 12:53 PM Alexandre Dutra <[email protected]> wrote: > > Hi Adnan, > > Sure, EventMetadata works for me. > > I think we are moving into implementation details a bit prematurely > though. We don't need the exact final design right now, as long as we > can demonstrate – as we did – that what's proposed can be easily > achieved. > > Thanks, > Alex > > On Sat, Oct 25, 2025 at 11:44 AM Adnan Hemani > <[email protected]> wrote: > > > > Hi Alex, > > > > Got it - with this suggestion, we will have to add this information > > manually into the Delegators (which are where we are emitting the events). > > Personally, this felt like a lot of repeated code for me that would be > > mixed in with the important parts of crafting the event and I was hoping > > not to crowd that logic - which is why I had pushed it out to the Event > > Listeners to take care of this there. This way, we were keeping the Java > > records crisp and not having to add the copy-paste logic into the event > > during event emission time. > > > > I fully agree with the philosophy that id, timestamp, and user information > > should be part of a PolarisEvent. But I still don’t think this suggested > > change is a great way to go, even though it may be the best option we have > > at the moment - so I’m torn. > > > > One thought to try to make the repeated code concise is to use an > > “EventMetadata” record that would become the parent of the id, timestamp, > > and user fields - and have the “EventMetadata” record be part of the > > PolarisEvent interface. We can then add a quick helper method wherever > > required to generate a new “EventMetadata” record - and we can limit the > > bloating of the Event record variables. Any further PolarisEvent-wide > > variables should be then added to the “EventMetadata” record as well. I > > know this option is not ideal either - but presents the functionality at > > the least impact to the code that I can see. WDYT? (Sample code in > > Appendix, if it’s helpful :) > > > > Best, > > Adnan Hemani > > > > —— > > Appendix: > > > > public record EventMetadata(UUID uuid, Instant timestamp, PolarisPrincipal > > user); > > > > public interface PolarisEvent { > > EventMetadata eventMetadata(); > > default static UUID createEventId() { return UUID.randomUUID(); } > > } > > > > public record BeforeSomethingEvent(String someParam, EventMetadata em) > > implements PolarisEvent {} > > > > Instantiation: > > > > @Inject SecurityContext securityContext; > > @Inject Clock clock; > > > > private EventMetadata createEventMetadata() { > > return new EventMetadata(PolarisEvent.createEventId(), clock.instant(), > > (PolarisPrincipal) securityContext.getUserPrincipal()); > > } > > > > new BeforeSomethingEvent(“abcd”, createEventMetadata()); > > > > > On Oct 24, 2025, at 2:40 AM, Alexandre Dutra <[email protected]> wrote: > > > > > > 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 > > >>>>> > > >> > >
