We now expose spring.modulith.events.externalization.enabled that can be set to false to disable the event externalization completely. Useful in test cases, for example.
We now allow externalizing application events to a variety of message brokers through the addition of Spring Modulith modules for Kafka, AMQP and JMS to a user project's classpath. Which events shall be externalized and how they're supposed to be routed to the message broker can be configured through either annotations or via a configuration API declared as Spring bean.
In case Jackson is on the classpath, we also add auto-configuration to use a Boot-configured ObjectMapper instance with the corresponding message broker client APIs to properly serialize and deserialize messages to JSON.
Introduce a new spring-modulith-events-api artifact to contain types that are supposed to be used by application code to deal with event publications. `EventPublication` was moved into that artifact and got everything non infrastructure related extracted from it's previous incarnation. That in turn has been renamed to `TargetEventPublication`.
`CompletedEventPublications` exposes API to allow purging completed publications either by a given predicate or age (in `Duration`). The interface is implemented by `DefaultEventPublicationRegistry` and thus subject for dependency injection into user code. It primarily delegates to the corresponding methods on `EventPublicationRepository` adapting the given `Duration`s to the `Clock` instance already held internally.
`IncompleteEventPublications` allows triggering the re-submission of incomplete publications by the same criteria as `CEP`. The interface is implemented by `PersistentApplicationEventMulticaster` and this subject for dependency injection into user code.
`EventPublicationRepository` now also allows publications to be deleted by identifiers. The existing implementations have been adapted and batch the requests for every 100 identifiers to prevent a list too large to run into limitations of the underlying data store.
Polished transactional metadata declaration in JPA- and MongoDB-based repository implementations.
Tightened nullability expressions here and there.
Added a readme to briefly describe what's contained in the examples. Added Maven Wrapper to all example projects.
Limit the dependencies of the JDBC based example to sole Spring JDBC (dropping the Spring Data integration as it's not needed for the example. Remove unused, JPA-related property
The default propagation type of @Transactional is Propagation.REQUIRED. That, however would reuse the already running committed transaction which is not the correct behavior.
Related ticket: #80.
As the Event Publication registry only works in transactional environments, we should enable them for MongoDB by default. This will require a replica setup for the MongoDB instance the application interacts with.
We now register default groupings for the architectural abstractions [0] in case they are available on the classpath but still fall back to the standard Spring Framework ones if not. In other words, if you e.g. use the jmolecules-hexagonal-architecture ones, types and packages annotated with @Port will cause the affected types to appear under a "Ports" section in the "Spring components" row in the Application Module Canvas.
[0] https://github.com/xmolecules/jmolecules#available-libraries-1
We now provide a ScenarioCustomizer that can be used to prepare Scenario instances for test methods with a common customizer. This avoids the need to call ….customize(…) for all Scenarios declared in a test class with the same logic.
Renamed top-level section to "Production-ready features" to align with Spring Boot. Moved actuator support before observability one. Introduced introductory section to showcase the Insight starter.
To make sure that we trigger transactional event listeners from Scenario based integration tests, we trigger stimulus executions using transactions configured to require a new transaction. This makes sure that Scenarios work in integration tests using @Transactional, of course circumventing the default rollback behavior of those transactions. There's no other way to implement this as we *need* to commit a transaction to trigger the delivery of transaction-bound events.
Fixed a bug in the handling of Scenario.stimulus(Supplier<T>) as for this, the Supplier handed into the method had not been executed transactionally at all.
Introduce Spring Modulith Actuator module to expose the application module structure as Spring Boot actuator. This required a Spring Modulith Runtime module to be extracted from the Spring Modulith Observability one. The former now contains the auto-configured ApplicationRuntime and ApplicationModulesRuntime bean instances to be able to bootstrap a ApplicationModules asynchronously on application startup. The actuator module then contains a Spring Boot @Endpoint implementation consuming the ApplicationModules to render JSON describing the application module structure.
We now provide @ApplicationModuleIntegrationListener as shortcut for the combination of @Async @Transactional @TransactionalEventListener to provide a dedicated annotation for the recommended integration arrangement.