Live Coding Journal - Feb 11, 2026
Reflections, Learnings, and Mistakes from live coding my JitterTicket Event Sourcing application
Notes from Today’s Live Coding Session
Today I finished the final piece of the ConcertStartedProcessor where the Concert.stopTicketSales() command method is called as a result of the ScheduledFuture being executed by the ScheduledExecutorService.
It took a bit of sketching code to figure out what the types should be for the nested lambdas (you might be amused to find me writing some old skool anonymous inner classes!), which turned out to be very much like defining partial functions.
The three levels of nesting of the lambdas didn’t make things any easier.
Command Executor Factory
This is where I ended up with the CommandExecutorFactory, which is a “Unit of Work Composer”:
- The outermost lambda is the
Runnablethat is passed to theScheduledExecutorServicewhen scheduling the “alarm” that will be executed at the concert’s show date and time. - The next level is the “infrastructure” or “unit of work” wrapper that does the work of loading the
Concertaggregate from the event store, calling the inner lambda, and the persisting any changes back to the event store. - The innermost level is the command method, in this case the literal method handle
Concert::stopTicketSales.
And this is what it looks like in the code when creating one of these wrappers for testing purposes:
// create the factory configured with the event store for Concerts
CommandExecutorFactory factory = CommandExecutorFactory.create(concertEventStore);
// create the innermost lambda that executes the desired command method on Concert
Command<Concert> command = Concert::stopTicketSales;
// ask the factory to wrap (compose) the method-level command with the infrastructure handling code
Command<ConcertId> commandExecutor = factory.wrap(command);
Now, when I want to wrap any Concert command method that needs the infrastructure to handle persistence, everything is the same except for the innermost Command<Concert>.
This is what the ConcertStartedProcessor does when scheduling that command in the scheduleAlarm method:
ScheduledFuture<?> scheduledFuture = scheduledExecutorService
.schedule(() -> commandExecutorFactory
.wrap(Concert::stopTicketSales)
.execute(concertId),
delayFromNowInMinutes(showDateTime),
TimeUnit.MINUTES
);
where that first parameter is the outermost lambda—a Runnable—that will invoke the unit of work to stop ticket sales.
I still have work to do to generalize this command-method invocation, because stopTicketSales doesn’t take any parameters, but the other command methods (e.g., schedule, reschedule) need at least a couple of parameters.
I’ll also need to deal with the different unit of work around command methods that do “creation” of the aggregate, e.g., Concert.schedule() and Customer.register(), since neither one has an aggregate to load from persistence (they still need to save, of course).
Tedbits
After some weirdness with resetting the database so I could create sample data that would demonstrate that the scheduled futures actually get executed, I was able to see the processor doing its job, because a concert that started 10 seconds after the application started no longer appeared in the “Available Concerts” projection.
This was actually a problem because my event viewer for Concerts was using the same projection!
Oops, I’ll have to create another projection that has all Concerts ever scheduled.
Luckily they’re straightforward to write now that the infrastructure wrapper for them (the ProjectionCoordinator) exists.
We had some good side discussions about James Shore’s “Nullables” and how they might seem to violate the “don’t put test code in production code” rule. As I said on the stream:
“The reason why you want to put these creation methods in the production code is the production code knows more about what it needs [and what its dependencies need] and is more resilient in the face of refactorings.”
Next Steps
Besides the new projection for all Concerts, and the further generalization of the CommandExecutorFactory, I want to add a UI for both the Schedule Concert and Reschedule Concert use cases. I hadn’t needed them when my focus was on figuring out Event-Sourcing, but it’ll be good to get the entire process implemented to see where I might have holes in the implementation. (This is the downside of doing inside-out development, you don’t know what might be needed by the outer layers of the application until they’re implemented.)
Join me on my next stream, which I usually do Monday through Thursday, starting at 20:00 UTC on Twitch: https://jitterted.stream.