Skip to content

Commit c8693cf

Browse files
Code adjustments based on PR review comments.
1 parent 6a21fd0 commit c8693cf

File tree

8 files changed

+111
-91
lines changed

8 files changed

+111
-91
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ default: `none`. Several options are available:
3939

4040
* `preview_payload_only` – payloads of events are visible via the API or UI, but snapshot loading is disabled.
4141

42-
* `load_snapshot_only` – event payloads are not shown, but snapshot loading is enabled for aggregate reconstruction.
42+
* `load_domain_state_only` – event payloads are not shown, but domain state loading is enabled for the domain entity.
4343

4444
* `full` – full access: event payloads are visible, and aggregate loading is supported.
4545

console-framework-client-api/src/main/java/io/axoniq/console/framework/api/Routes.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ object Routes {
6666
const val REPORT = "application-info-report"
6767
}
6868

69-
object Aggregate {
70-
const val DOMAIN_EVENTS = "aggregate-domain-events"
71-
const val LOAD_FOR_AGGREGATE = "load-for-aggregate"
69+
object Enity {
70+
const val DOMAIN_EVENTS = "domain-events"
71+
const val ENTITY_STATE_AT_SEQUENCE = "entity-state-at-sequence"
7272
}
7373

7474
object MessageFlow {

console-framework-client-api/src/main/java/io/axoniq/console/framework/api/aggregateApi.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package io.axoniq.console.framework.api
33
import java.time.Instant
44

55
data class DomainEventsResult(
6-
val aggregateId: String,
7-
val aggregateType: String,
6+
val entityId: String,
7+
val entityType: String,
88
val domainEvents: List<DomainEvent>,
99
val page: Int,
1010
val pageSize: Int,
@@ -19,20 +19,20 @@ data class DomainEvent(
1919
)
2020

2121
data class DomainEventsQuery(
22-
val aggregateId: String,
22+
val entityId: String,
2323
val page: Int = 0,
2424
val pageSize: Int = 10,
2525
)
2626

27-
data class AggregateSnapshotResult(
27+
data class EntityStateResult(
2828
val type: String,
29-
val aggregateId: String,
29+
val entityId: String,
3030
val maxSequenceNumber: Long = 0,
31-
val snapshot: String,
31+
val state: String,
3232
)
3333

34-
data class AggregateSnapshotQuery(
34+
data class EntityStateAtSequenceQuery(
3535
val type: String,
36-
val aggregateId: String,
36+
val entityId: String,
3737
val maxSequenceNumber: Long = 0,
3838
)

console-framework-client/pom.xml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,6 @@
2323
<artifactId>console-framework-client-parent</artifactId>
2424
<version>1.9.3-SNAPSHOT</version>
2525
</parent>
26-
<build>
27-
<plugins>
28-
<plugin>
29-
<groupId>org.apache.maven.plugins</groupId>
30-
<artifactId>maven-compiler-plugin</artifactId>
31-
<configuration>
32-
<source>16</source>
33-
<target>16</target>
34-
</configuration>
35-
</plugin>
36-
</plugins>
37-
</build>
3826
<modelVersion>4.0.0</modelVersion>
3927

4028
<artifactId>console-framework-client</artifactId>

console-framework-client/src/main/java/io/axoniq/console/framework/AxoniqConsoleConfigurerModule.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616

1717
package io.axoniq.console.framework;
1818

19-
import io.axoniq.console.framework.application.AggregateEventStreamProvider;
19+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
20+
import com.fasterxml.jackson.annotation.PropertyAccessor;
21+
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import io.axoniq.console.framework.application.DomainEventStreamProvider;
2023
import io.axoniq.console.framework.application.ApplicationMetricRegistry;
2124
import io.axoniq.console.framework.application.ApplicationMetricReporter;
2225
import io.axoniq.console.framework.application.ApplicationReportCreator;
2326
import io.axoniq.console.framework.application.ApplicationThreadDumpProvider;
24-
import io.axoniq.console.framework.application.RSocketAggregateDataResponder;
27+
import io.axoniq.console.framework.application.RSocketDomainEntityDataResponder;
2528
import io.axoniq.console.framework.application.RSocketThreadDumpResponder;
2629
import io.axoniq.console.framework.client.AxoniqConsoleRSocketClient;
2730
import io.axoniq.console.framework.client.ClientSettingsService;
@@ -93,6 +96,7 @@ public class AxoniqConsoleConfigurerModule implements ConfigurerModule {
9396
private final EventScheduler eventScheduler;
9497
private final MeterRegistry meterRegistry = new SimpleMeterRegistry();
9598
private final String instanceName;
99+
private final ObjectMapper objectMapper;
96100

97101
/**
98102
* Creates the {@link AxoniqConsoleConfigurerModule} with the given {@code builder}.
@@ -116,6 +120,7 @@ protected AxoniqConsoleConfigurerModule(Builder builder) {
116120
this.configureSpanFactory = !builder.disableSpanFactoryInConfiguration;
117121
this.spanMatcherPredicateMap = builder.spanMatcherPredicateMap;
118122
this.eventScheduler = builder.eventScheduler;
123+
this.objectMapper = builder.objectMapper;
119124
}
120125

121126
/**
@@ -227,9 +232,10 @@ public void configureModule(@NotNull Configurer configurer) {
227232
.registerComponent(ApplicationThreadDumpProvider.class,
228233
c -> new ApplicationThreadDumpProvider()
229234
)
230-
.registerComponent(AggregateEventStreamProvider.class,
231-
c -> new AggregateEventStreamProvider(
232-
configurer.buildConfiguration()
235+
.registerComponent(DomainEventStreamProvider.class,
236+
c -> new DomainEventStreamProvider(
237+
configurer.buildConfiguration(),
238+
objectMapper
233239
)
234240
)
235241
.registerComponent(RSocketDlqResponder.class,
@@ -242,9 +248,9 @@ public void configureModule(@NotNull Configurer configurer) {
242248
c.getComponent(ApplicationThreadDumpProvider.class),
243249
c.getComponent(RSocketHandlerRegistrar.class)
244250
))
245-
.registerComponent(RSocketAggregateDataResponder.class,
246-
c -> new RSocketAggregateDataResponder(
247-
c.getComponent(AggregateEventStreamProvider.class),
251+
.registerComponent(RSocketDomainEntityDataResponder.class,
252+
c -> new RSocketDomainEntityDataResponder(
253+
c.getComponent(DomainEventStreamProvider.class),
248254
c.getComponent(RSocketHandlerRegistrar.class),
249255
domainEventAccessMode,
250256
c.eventSerializer()
@@ -275,7 +281,7 @@ public void configureModule(@NotNull Configurer configurer) {
275281
c.getComponent(RSocketDlqResponder.class);
276282
c.getComponent(HandlerMetricsRegistry.class);
277283
c.getComponent(RSocketThreadDumpResponder.class);
278-
c.getComponent(RSocketAggregateDataResponder.class);
284+
c.getComponent(RSocketDomainEntityDataResponder.class);
279285
});
280286

281287
configurer.onStart(() -> {
@@ -329,6 +335,9 @@ public static class Builder {
329335
private Integer managementMaxThreadPoolSize = 5;
330336
private EventScheduler eventScheduler;
331337

338+
private ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules()
339+
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
340+
332341
/**
333342
* Constructor to instantiate a {@link Builder} based on the fields contained in the
334343
* {@link AxoniqConsoleConfigurerModule.Builder}. Requires the {@code environmentId}, {@code accessToken} and
@@ -554,6 +563,19 @@ public Builder eventScheduler(EventScheduler eventScheduler) {
554563
return this;
555564
}
556565

566+
/**
567+
* Set the object mapper to be used for serialization and deserialization of domain events.
568+
* Defaults to a new {@link ObjectMapper} with all modules registered and field visibility set to any.
569+
*
570+
* @param objectMapper the object mapper to use
571+
* @return The builder for fluent interfacing
572+
*/
573+
public Builder objectMapper(ObjectMapper objectMapper) {
574+
BuilderUtils.assertNonNull(objectMapper, "Object mapper must be non-null");
575+
this.objectMapper = objectMapper;
576+
return this;
577+
}
578+
557579
/**
558580
* Builds the {@link AxoniqConsoleConfigurerModule} based on the fields set in this {@link Builder}.
559581
*

console-framework-client/src/main/java/io/axoniq/console/framework/DomainEventAccessMode.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22

33
public enum DomainEventAccessMode {
44
/**
5-
* Full access: payload is visible and LoadForAggregate is supported.
5+
* Full access: payload is visible and loading domain state is supported.
66
*/
77
FULL,
88

99
/**
10-
* Payload is hidden (e.g., masked or removed), but LoadForAggregate is still supported.
10+
* Payload is hidden (e.g., masked), but loading domain state is still supported.
1111
*/
12-
LOAD_SNAPSHOT_ONLY,
12+
LOAD_DOMAIN_STATE_ONLY,
1313

1414
/**
15-
* Payload is visible, but LoadForAggregate is not supported.
15+
* Payload is visible, but loading domain state is not supported.
1616
*/
1717
PREVIEW_PAYLOAD_ONLY,
1818

1919
/**
20-
* No access: payload is hidden and LoadForAggregate is not supported.
20+
* No access: payload is hidden and loading domain state is not supported.
2121
*/
2222
NONE
2323
}

console-framework-client/src/main/java/io/axoniq/console/framework/application/AggregateEventStreamProvider.kt renamed to console-framework-client/src/main/java/io/axoniq/console/framework/application/DomainEventStreamProvider.kt

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.axoniq.console.framework.application
22

3+
import com.fasterxml.jackson.databind.ObjectMapper
34
import org.axonframework.common.ReflectionUtils
45
import org.axonframework.config.AggregateConfiguration
56
import org.axonframework.config.Configuration
@@ -14,34 +15,39 @@ import org.axonframework.modelling.command.Repository
1415
import org.axonframework.modelling.command.RepositoryProvider
1516
import org.axonframework.modelling.command.inspection.AggregateModel
1617

17-
class AggregateEventStreamProvider(
18-
private val configuration: Configuration
18+
class DomainEventStreamProvider(
19+
private val configuration: Configuration,
20+
private val objectMapper: ObjectMapper
1921
) {
2022

21-
fun getDomainEventStream(aggregateIdentifier: String): List<DomainEventMessage<*>>? =
22-
configuration.eventStore().readEvents(aggregateIdentifier, 0).asStream().toList()
23-
23+
fun getDomainEventStream(entityIdentifier: String, firstSequenceNumber: Long = 0): List<DomainEventMessage<*>>? =
24+
configuration.eventStore()
25+
.readEvents(entityIdentifier, firstSequenceNumber)
26+
.iterator()
27+
.asSequence()
28+
.toList()
29+
.takeIf { it.isNotEmpty() }
2430

25-
fun <T> loadForAggregate(type: String, identifier: String, maxSequenceNumber: Long): String? {
26-
val aggregateConfiguration = configuration.modules
31+
fun <T> loadDomainStateAtSequence(type: String, entityIdentifier: String, maxSequenceNumber: Long): String? {
32+
val entityConfiguration = configuration.modules
2733
.filterIsInstance<AggregateConfiguration<*>>()
2834
.firstOrNull { it.aggregateType().simpleName == type }
29-
?: throw IllegalArgumentException("No aggregate found for type $type")
35+
?: throw IllegalArgumentException("No domain entity found for type $type")
3036

3137
val eventStore = configuration.eventStore()
3238

33-
val factory: AggregateFactory<T> = aggregateConfiguration.aggregateFactory() as AggregateFactory<T>
34-
val model: AggregateModel<T> = aggregateConfiguration.repository().getPropertyValue<AggregateModel<T>>("aggregateModel")
35-
?: throw IllegalArgumentException("No aggregate model found for type $type")
39+
val factory: AggregateFactory<T> = entityConfiguration.aggregateFactory() as AggregateFactory<T>
40+
val model: AggregateModel<T> = entityConfiguration.repository().getPropertyValue<AggregateModel<T>>("aggregateModel")
41+
?: throw IllegalArgumentException("No domain entity model found for type $type")
3642

37-
val stream = readEvents(identifier)
38-
val loadingAggregate: EventSourcedAggregate<T> = EventSourcedAggregate
39-
.initialize(factory.createAggregateRoot(identifier, stream.peek()),
43+
val stream = readEvents(entityIdentifier)
44+
val loadingEntity: EventSourcedAggregate<T> = EventSourcedAggregate
45+
.initialize(factory.createAggregateRoot(entityIdentifier, stream.peek()),
4046
model,
4147
eventStore,
4248
object : RepositoryProvider {
4349
override fun <T> repositoryFor(aggregateType: Class<T>): Repository<T> {
44-
return aggregateConfiguration.repository() as Repository<T>
50+
return entityConfiguration.repository() as Repository<T>
4551
}
4652

4753
},
@@ -55,15 +61,15 @@ class AggregateEventStreamProvider(
5561
}
5662
})
5763

58-
loadingAggregate.initializeState(stream.filter { it.sequenceNumber <= maxSequenceNumber })
64+
loadingEntity.initializeState(stream.filter { it.sequenceNumber <= maxSequenceNumber })
5965

60-
return configuration.serializer().serialize(loadingAggregate.aggregateRoot, String::class.java).data
66+
return objectMapper.writeValueAsString(loadingEntity.aggregateRoot)
6167
}
6268

63-
private fun readEvents(identifier: String): DomainEventStream =
69+
private fun readEvents(identifier: String, firstSequenceNumber: Long = 0): DomainEventStream =
6470
configuration.eventStore()
6571
.getPropertyValue<AbstractEventStorageEngine>("storageEngine")
66-
?.readEvents(identifier, 0)
72+
?.readEvents(identifier, firstSequenceNumber)
6773
?: throw IllegalStateException("Unable to find AbstractEventStorageEngine in event store")
6874

6975
@Suppress("UNCHECKED_CAST")

0 commit comments

Comments
 (0)