Archive for March 2025

Week 14, year 2025

  • MediatR 12.5.0 Released - I pushed out MediatR 12.5 today: Release Notes NuGet This is mainly a regular minor release with a couple extra interesting features: Adding convenience method to register open behaviors Better cancellation token support (it's passed now everywhere including behaviors) And some other cleanup items as well. Enjoy! [Jimmy Bogard]
  • I've been kidnapped by Robert Caro - I've always enjoyed reading, and for most of my life I've particularly enjoyed reading history. I've head many great things about Robert Caro's books, but was deterred by their size. Finally, with his first book newly available as an ebook, I decided to dip my toes in. The books are too good for me to escape. [Martin Fowler]
  • AutoMapper and MediatR Going Commercial - Yes, another one of "those posts". But tl;dr: In order to ensure the long-term sustainability of my OSS projects, I will be commercializing AutoMapper and MediatR. I did not post this on April 1st for obvious reasons. But first a little background on how I got to [Jimmy Bogard]
  • Social Media Engagement in Early 2025 - A few years ago, whenever I published a new article here, I would just announce it on Twitter, but since the Muskover its importance has declined, and now I post updates to several services. To compare engagement on these services, I've looked at reposts, likes, and replies to two dozen of my recent posts. [Martin Fowler]
  • Updating yesterday's post on social media engagement - Some people asked about how many people clicked through the links on these social media posts. I've added some more to the article, partly to explain why I don't have that information, and partly to show overall source data for traffic to the site. [Martin Fowler]
Permalink | From 31 March 2025 to 06 April 2025 | Last updated on: Fri, 4 Apr 2025 23:19:32 GMT

Week 13, year 2025

  • The role of developer skills in agentic coding - As agentic coding assistants get more capable, Birgitta Böckeler is trying them to change existing codebases. This has led to some impressive collaboration sessions, but she's needed to intervene, correct and steer all the time. In her latest post, she describes examples of these interventions, giving ideas of the types of skills we currently need to correct the tools' missteps. [Martin Fowler]
Permalink | From 24 March 2025 to 30 March 2025 | Last updated on: Tue, 25 Mar 2025 15:19:29 GMT

Week 11, year 2025

  • New Eventuate platform APIs that support Async API: part 1 - events - New Eventuate platform APIs that support Async API: part 1 - events I recently developed a plugin for SpringWolf that configures an Eventuate service to expose an /springwolf/docs endpoint that returns an Async API document describing the messages that the service sends and receives. While implementing the plugin, however, I discovered that the existing Eventuate APIs were not well suited to exposing Async API-style metadata. For example, the messages sent by the service — and the channels to which it sent them — were not explicitly defined; instead, these details were hidden within the code This realization prompted the creation of a new set of Eventuate APIs for sending and receiving messages. The old APIs still work but only limited metadata can be generated from them. In this article, I’ll describe the new APIs for publishing and subscribing to events. A later article will describe the new APIs for commands and sagas. Let’s first look at the changes to event publishing. Event publishing Let’s first look at the old way of publishing events. After that I describe the new approach. Original event publishing API Previously, domain logic simply used the DomainEventPublisher to publish events: publicclassCustomerService{privateDomainEventPublisherdomainEventPublisher;@TransactionalpublicCustomercreateCustomer(Stringname,MoneycreditLimit){...domainEventPublisher.publish(Customer.class,customer.getId(),customerWithEvents.events);returncustomer;} As a result, the channels and event types were not explicitly defined. New event publishing API The new approach consists of defining one or more DomainEventPublisherForAggregate@Beans. A DomainEventPublisherForAggregate publishes events for a specific aggregate. Although defining DomainEventPublisherForAggregates involves more code, it explicitly defines the channels and events. The Eventuate plugin for Spring Wolf uses the DomainEventPublisherForAggregate@Beans to generate an Async API document describing the published events and their channels. Here’s the definition of a DomainEventPublisherForAggregate for the Customer aggregate: publicinterfaceCustomerEventPublisherextendsDomainEventPublisherForAggregate<Customer,Long,CustomerEvent>{} It’s injected into the CustomerService: publicclassCustomerService{privatefinalCustomerEventPublishercustomerEventPublisher;publicvoidreserveCredit(longorderId,longcustomerId,MoneyorderTotal){CustomerCreditReservedEventcustomerCreditReservedEvent=newCustomerCreditReservedEvent(customerId,orderId);customerEventPublisher.publish(customer,customerCreditReservedEvent); Finally, here is the @Bean implementation of the CustomerEventPublisher: @ComponentpublicclassCustomerEventPublisherImplextendsAbstractDomainEventPublisherForAggregateImpl<Customer,Long,CustomerEvent>implementsCustomerEventPublisher{publicCustomerEventPublisherImpl(DomainEventPublisherdomainEventPublisher){super(Customer.class,Customer::getId,domainEventPublisher,CustomerEvent.class);}} Let’s now look at the new event handling API. Subscribing to events Let’s first look at the old way of subscribing to events. After that I describe the new approach. Original event handling API Previously, event handlers were configured by defining a class that constructed DomainEventHandlers: publicclassOrderEventConsumer{publicDomainEventHandlersdomainEventHandlers(){returnDomainEventHandlersBuilder.forAggregateType("io.eventuate.examples.tram.ordersandcustomers.orders.domain.Order").onEvent(OrderCreatedEvent.class,this::handleOrderCreatedEvent)....build();}publicvoidhandleOrderCreatedEvent(DomainEventEnvelope<OrderCreatedEvent>domainEventEnvelope){... The DomainEventHandlers was then passed to a DomainEventDispatcherFactory: publicclassCustomerConfiguration{@BeanpublicOrderEventConsumerorderEventConsumer(CustomerServicecustomerService){returnnewOrderEventConsumer(customerService);}@BeanpublicDomainEventDispatcherdomainEventDispatcher(OrderEventConsumerorderEventConsumer,DomainEventDispatcherFactorydomainEventDispatcherFactory){returndomainEventDispatcherFactory.make("orderServiceEvents",orderEventConsumer.domainEventHandlers());} The Eventuate plugin for Spring Wolf can use the DomainEventDispatcher@Beans to generate an Async API document describing the subscribed to events and their channels. However, there’s no obvious way to customize the Async API document by, for example, specifying additional documentation. New event handling API The new approach is to define beans that have methods annotated with @EventuateDomainEventHandler. The annotation specifies the event handler’s subscriber ID and the channel. The event type is obtained from the method parameter. @ComponentpublicclassOrderEventConsumer{privateLoggerlogger=LoggerFactory.getLogger(getClass());privateCustomerServicecustomerService;publicOrderEventConsumer(CustomerServicecustomerService){this.customerService=customerService;}@EventuateDomainEventHandler(subscriberId="OrderEventConsumer",channel="io.eventuate.examples.tram.ordersandcustomers.orders.domain.Order")publicvoidhandleOrderCreatedEvent(DomainEventEnvelope<OrderCreatedEvent>domainEventEnvelope){OrderCreatedEventevent=domainEventEnvelope.getEvent();customerService.reserveCredit(Long.parseLong(domainEventEnvelope.getAggregateId()),event.orderDetails().customerId(),event.orderDetails().orderTotal());} The Eventuate plugin for Spring Wolf can search the application context for @Beans that have methods annotated with @EventuateDomainEventHandler. Moreover, in the future, it will support additional annotations that allow you to customize the generated Async API document. Show me the code The Eventuate Spring Wolf repository contains some example Async API docs The development branch of the eventuate-tram-examples-customers-and-orders repository contains an example application that uses the new APIs. What’s next A later post will describe the new APIs for sagas and command handlers. [Eventuate, Inc]
Permalink | From 10 March 2025 to 16 March 2025 | Last updated on: Wed, 12 Mar 2025 07:19:36 GMT