Skip to content

Drive model inspection through real UnitOfWork and support modules#153

Merged
stefanmirkovic merged 1 commit intofeature/af5-model-inspectionfrom
feature/af5-model-inspection-mitchell-proposal
May 6, 2026
Merged

Drive model inspection through real UnitOfWork and support modules#153
stefanmirkovic merged 1 commit intofeature/af5-model-inspectionfrom
feature/af5-model-inspection-mitchell-proposal

Conversation

@CodeDrivenMitch
Copy link
Copy Markdown
Collaborator

This is a proposal PR to the original PR posed by Mirko, #146. It takes a different approach to the same problem, and functionally nothing has changed

Why the proposal

The original approach was very reflection-heavy, which is partly to be expected, but can also be improved upon. The more inner reflection is present, the more likely it's to break.

In addition, the approach didn't account for entites in submodules for hierarchic contexts. As such, only top-level entities would be discovered.

As this all requires very deep knowledge about how the Configuration of Axon Framework works, I decided to make this proposal PR to guide by example, instead of separate comments.

Basics of the rewrite

  1. The UnitOfWorkFeactory.create() is used during all sourcing and read operations. This way all parameter resolvers will work correctly. This takes away the need of manually invoking methods.
  2. Repository instances are discovered at boot time. If it's an EventSourcingRepository, it's registeredd to the RSocketModelInspectionResponder
  3. The EventSourcingRepository is rebuilt using reflection to be able to decorate the EntityEvolver with the AxoniqPlatformEntityEvolver.
  4. Reading the event stream and entity state is now a Repository.load(...) operation. Several resources are put in the ProcessingContext, which the decorators respond to. a. AxoniqPlatformEntityEvolver.BEFORE_CONSUMER: If present, calls with the entity state before any evolve b. AxoniqPlatformEntityEvolver.AFTER_CONSUMER: If present, calls with the entity state after any evolve c. AxoniqPlatformEntityEvolver.MAX_INDEX: Stops evolving the entity after a certain index.

Result

With the new code a lot of the reflection-based code could be deleted. The RSocketModelInspectionResponder.kt shrunk by half its size. We have programmed against the interfaces of the framework, which are less likely to change.

In addition I added tests that confirm it works.

This is a proposal PR to the original PR posed by Mirko, #146. It takes a different approach to the same problem, and functionally nothing has changed

## Why the proposal

The original approach was very reflection-heavy, which is partly to be expected, but can also be improved upon. The more inner reflection is present, the more likely it's to break.

In addition, the approach didn't account for entites in submodules for hierarchic contexts. As such, only top-level entities would be discovered.

As this all requires very deep knowledge about how the Configuration of Axon Framework works, I decided to make this proposal PR to guide by example, instead of separate comments.

## Basics of the rewrite

1. The `UnitOfWorkFeactory.create()` is used during all sourcing and read operations. This way all parameter resolvers will work correctly. This takes away the need of manually invoking methods.
2. Repository instances are discovered at boot time. If it's an EventSourcingRepository, it's registeredd to the `RSocketModelInspectionResponder`
3. The `EventSourcingRepository` is rebuilt using reflection to be able to decorate the `EntityEvolver` with the `AxoniqPlatformEntityEvolver`.
4. Reading the event stream and entity state is now a `Repository.load(...)` operation. Several resources are put in the `ProcessingContext`, which the decorators respond to.
  a. `AxoniqPlatformEntityEvolver.BEFORE_CONSUMER`: If present, calls with the entity state before any evolve
  b. `AxoniqPlatformEntityEvolver.AFTER_CONSUMER`: If present, calls with the entity state after any evolve
  c. AxoniqPlatformEntityEvolver.MAX_INDEX: Stops evolving the entity after a certain index.

## Result

With the new code a lot of the reflection-based code could be deleted. The RSocketModelInspectionResponder.kt shrunk by half its size. We have programmed against the interfaces of the framework, which are less likely to change.

In addition I added tests that confirm it works.
@CodeDrivenMitch CodeDrivenMitch self-assigned this May 5, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

@stefanmirkovic stefanmirkovic merged commit 22023b1 into feature/af5-model-inspection May 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants