-
Notifications
You must be signed in to change notification settings - Fork 0
Introduce Axon Framework 5 support #108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Axon Framework 5 is out, and its configuration is fundamentally different. As such: - This module has been renamed to the Axoniq Platform client, formerly AxonIQ Console Framework client - The modules have been split similar to the modules of the framework, allowing users to not use a part of the framework - Aggregate support has been dropped - DLQ support has been dropped - Instrumentation now works via decorators instead of the `SpanFactory` mechanism, propagating its measurements via the `ProcessingContext` - Repository loads are now reported with the handler itself - The module is now activated by registering an AxoniqPlatformProperties object to the ComponentRegistry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces support for Axon Framework 5 with significant architectural changes. The module has been renamed from "AxonIQ Console Framework client" to "Axoniq Platform client" and refactored into multiple modules (messaging, modelling, eventsourcing). The instrumentation mechanism has been completely redesigned, moving from the SpanFactory pattern to decorators that propagate measurements via ProcessingContext. Aggregate and DLQ support have been removed, and the module is now activated by registering an AxoniqPlatformProperties object to the ComponentRegistry.
Key Changes:
- Upgraded to Java 17, Axon Framework 5.0.0, Spring Boot 3.5.7, and Kotlin 2.2.20
- Replaced SpanFactory-based instrumentation with decorator pattern using ProcessingContext
- Split monolithic module into separate messaging, modelling, and eventsourcing modules
- Removed aggregate and DLQ support functionality
Reviewed Changes
Copilot reviewed 122 out of 122 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Updated project coordinates, versions, and module structure for AF5 compatibility |
| axoniq-platform-client-messaging/* | New core messaging module with decorator-based instrumentation |
| axoniq-platform-client-modelling/* | New modelling module for repository instrumentation |
| axoniq-platform-client-eventsourcing/* | New eventsourcing module for event storage engine instrumentation |
| axoniq-platform-client-spring-boot-starter/* | Updated Spring Boot starter for simplified configuration |
| console-framework-client/* | Removed old AF4-based implementation files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private fun waitForProcessorToHaveClaimedSegment( | ||
| processor: StreamingEventProcessor, | ||
| segmentId: Int, | ||
| ): Boolean { | ||
| var loop = 0 | ||
| while (loop < 300) { | ||
| Thread.sleep(100) | ||
| if (processor.processingStatus().containsKey(segmentId)) { | ||
| logger.debug("Processor [${processor.name()}] successfully claimed segment [$segmentId] in approx. [${loop * 100}ms].") | ||
| return true | ||
| } | ||
| loop++ | ||
| } | ||
|
|
||
| logger.debug("Processor [${processor.name()}] failed to claim [$segmentId] in approx. [${loop * 100}ms].") | ||
| return false | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can use Awaitility lib here... Something like:
import org.awaitility.Awaitility.*
import java.time.Duration
private fun waitForProcessorToHaveClaimedSegment(
processor: StreamingEventProcessor,
segmentId: Int
): Boolean {
return try {
await()
.atMost(Duration.ofSeconds(30))
.pollInterval(Duration.ofMillis(100))
.until { processor.processingStatus().containsKey(segmentId) }
true
} catch (e: Exception) {
logger.debug("Processor [${processor.name()}] failed to claim [$segmentId]")
false
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or alternatively, since we're using Kotlin, we can use coroutines, which don't block threads...
Something like:
suspend fun waitForProcessorToHaveClaimedSegment(
processor: StreamingEventProcessor,
segmentId: Int
): Boolean = withTimeout(30000) {
while (!processor.processingStatus().containsKey(segmentId)) {
delay(100)
}
true
}
or
suspend fun waitForProcessorToHaveClaimedSegment(
processor: StreamingEventProcessor,
segmentId: Int,
maxAttempts: Int = 300
): Boolean {
repeat(maxAttempts) { attempt ->
if (processor.processingStatus().containsKey(segmentId)) {
logger.debug("Processor [${processor.name()}] successfully claimed segment [$segmentId] after $attempt attempts")
return true
}
delay(100)
}
logger.debug("Processor [${processor.name()}] failed to claim [$segmentId] after $maxAttempts attempts")
return false
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to add another dependency to this library. This adds extra code to the user base, and we should avoid that. Awaitility is usually a test dependency, and this might thus conflict.
As for Kotlin, I'd like to move away from this in the future (I can't believe I haven't done it now), as we had several conflicts with clients on versioning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Really amazing work! 🙌 👏
|




Axon Framework 5 is out, and its configuration is fundamentally different. As such:
SpanFactorymechanism, propagating its measurements via theProcessingContextNote that deleted code will be recovered from Git in the future when we re-implement it, for example the domain event stream feature. There were unknown classes and therefore could not be kept at this point in time.