Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ build/
.vscode/

### Mac OS ###
.DS_Store
.DS_Store

### Docker ###
volumes

### App ###
logs
15 changes: 13 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,19 @@ services:
axoniq_axonserver_autocluster_first: axon-server
axoniq_axonserver_autocluster_contexts: _admin
volumes:
- data:/axonserver/data
- events:/axonserver/events
- ./volumes/axonserver-data:/axonserver/data
- ./volumes/axonserver-events:/axonserver/events
postgres:
image: postgres:18
environment:
POSTGRES_DB: university_demo_db
POSTGRES_USER: university_demo_user
POSTGRES_PASSWORD: university_demo_password
ports:
- "5444:5444"
volumes:
- ./volumes/postgres-axon:/var/lib/postgresql/18/docker
command: -p 5444

volumes:
db:
Expand Down
19 changes: 19 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
<axon-postgresql.version>0.1.0</axon-postgresql.version>
<postgresql.version>42.7.8</postgresql.version>
<hikari-cp.version>7.0.2</hikari-cp.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -61,6 +64,22 @@
<version>${axon.version}</version>
</dependency>

<dependency>
<groupId>io.axoniq.framework</groupId>
<artifactId>postgresql-core</artifactId>
<version>${axon-postgresql.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikari-cp.version}</version>
</dependency>

<!-- Serialization Dependencies -->

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
public class ConfigurationProperties {
private static final Logger logger = Logger.getLogger(ConfigurationProperties.class.getName());

boolean axonServerEnabled = true;
// Possible values: "in-memory", "axonserver", "postgres"
private String eventStorageEngine = "axonserver";

public static ConfigurationProperties defaults() {
return new ConfigurationProperties();
Expand All @@ -21,9 +22,9 @@ public static ConfigurationProperties load() {
Properties properties = loadPropertiesFile("application.properties");

if (properties != null) {
String axonServerEnabled = properties.getProperty("axon.server.enabled");
if (axonServerEnabled != null) {
props.axonServerEnabled = Boolean.parseBoolean(axonServerEnabled);
String engine = properties.getProperty("axon.event-storage.engine");
if (engine != null && !engine.isBlank()) {
props.eventStorageEngine = engine.trim();
}
} else {
logger.info("No properties file found, using default configuration");
Expand All @@ -46,12 +47,20 @@ private static Properties loadPropertiesFile(String filename) {
return null;
}

public boolean axonServerEnabled() {
return axonServerEnabled;
public String eventStorageEngine() {
return eventStorageEngine;
}

public ConfigurationProperties axonServerEnabled(boolean axonServerEnabled) {
this.axonServerEnabled = axonServerEnabled;
public ConfigurationProperties eventStorageEngine(String eventStorageEngine) {
this.eventStorageEngine = eventStorageEngine;
return this;
}

public boolean isAxonServerEventStorageEngine() {
return "axonserver".equalsIgnoreCase(eventStorageEngine);
}

public boolean isPostgresEventStorageEngine() {
return "postgres".equalsIgnoreCase(eventStorageEngine);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package io.axoniq.demo.university;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.axoniq.demo.university.faculty.FacultyModuleConfiguration;
import io.axoniq.demo.university.shared.ids.CourseId;
import io.axoniq.demo.university.faculty.write.createcourseplain.CreateCourse;
import io.axoniq.demo.university.faculty.write.renamecourse.RenameCourse;
import io.axoniq.framework.postgresql.DataSourceConnectionExecutor;
import io.axoniq.framework.postgresql.PostgresqlEventStorageEngine;
import org.axonframework.axonserver.connector.AxonServerConfiguration;
import org.axonframework.axonserver.connector.AxonServerConfigurationEnhancer;
import org.axonframework.commandhandling.gateway.CommandGateway;
import org.axonframework.common.infra.FilesystemStyleComponentDescriptor;
import org.axonframework.configuration.AxonConfiguration;
import org.axonframework.eventhandling.conversion.DelegatingEventConverter;
import org.axonframework.eventhandling.conversion.EventConverter;
import org.axonframework.eventsourcing.configuration.EventSourcingConfigurer;

import java.util.function.UnaryOperator;
Expand Down Expand Up @@ -53,7 +59,7 @@ public EventSourcingConfigurer configurer(
UnaryOperator<EventSourcingConfigurer> customization
) {
var configurer = EventSourcingConfigurer.create();
if (configProps.axonServerEnabled) {
if (configProps.isAxonServerEventStorageEngine()) {
configurer.componentRegistry(r -> r.registerComponent(AxonServerConfiguration.class, c -> {
var axonServerConfig = new AxonServerConfiguration();
axonServerConfig.setContext(CONTEXT);
Expand All @@ -62,6 +68,23 @@ public EventSourcingConfigurer configurer(
} else {
configurer.componentRegistry(r -> r.disableEnhancer(AxonServerConfigurationEnhancer.class));
}
if (configProps.isPostgresEventStorageEngine()) {
HikariConfig config = new HikariConfig();

config.setJdbcUrl("jdbc:postgresql://localhost:5444/university_demo_db");
config.setUsername("university_demo_user");
config.setPassword("university_demo_password");
config.setAutoCommit(false);
config.setMaximumPoolSize(5);
config.setMinimumIdle(1);

configurer.registerEventStorageEngine(cr ->
new PostgresqlEventStorageEngine(
new DataSourceConnectionExecutor(new HikariDataSource(config)),
cr.getComponent(EventConverter.class)
)
);
}
configurer = customization.apply(configurer);
return configurer;
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# University Demo Application Configuration
axon.server.enabled=true

# Options: in-memory / axonserver / postgres
axon.event-storage.engine=postgres
37 changes: 37 additions & 0 deletions src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>

<RollingFile name="RollingFileAppender" fileName="logs/application.log"
filePattern="logs/application-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
</Appenders>

<Loggers>
<!-- Axon Framework logging -->
<Logger name="org.axonframework" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFileAppender"/>
</Logger>

<!-- Application logging -->
<Logger name="io.axoniq.demo.university" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFileAppender"/>
</Logger>

<!-- Root logger for all other packages -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFileAppender"/>
</Root>
</Loggers>
</Configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ void beforeEach() {
}

private static void purgeAxonServerIfEnabled(ConfigurationProperties configuration) {
boolean axonServerEnabled = configuration.axonServerEnabled();
if (axonServerEnabled) {
boolean useAxonServer = configuration.isAxonServerEventStorageEngine();
if (useAxonServer) {
try {
AxonServerContainerUtils.purgeEventsFromAxonServer("localhost", 8024, "university", true);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public static AxonTestFixture slice(UnaryOperator<EventSourcingConfigurer> custo
var configuration = ConfigurationProperties.load();
var configurer = application.configurer(configuration, customization);
purgeAxonServerIfEnabled(configuration);
return AxonTestFixture.with(configurer, c -> configuration.axonServerEnabled() ? c : c.disableAxonServer());
return AxonTestFixture.with(configurer, c -> configuration.isAxonServerEventStorageEngine() ? c : c.disableAxonServer());
}

private static void purgeAxonServerIfEnabled(ConfigurationProperties configuration) {
boolean axonServerEnabled = configuration.axonServerEnabled();
if (axonServerEnabled) {
boolean useAxonServer = configuration.isAxonServerEventStorageEngine();
if (useAxonServer) {
try {
AxonServerContainerUtils.purgeEventsFromAxonServer("localhost", 8024, "university", true);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void successfulSubscription() {
.when()
.command(new SubscribeStudentToCourse(studentId, courseId))
.then()
.success()
.events(new StudentSubscribedToCourse(studentId, courseId));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void successfulSubscription() {
.when()
.command(new SubscribeStudentToCourse(studentId, courseId))
.then()
.success()
.events(new StudentSubscribedToCourse(studentId, courseId));
}

Expand Down
5 changes: 3 additions & 2 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# University Demo Test Configuration
axon.server.enabled=false
# University Demo Application Configuration

# Options: in-memory / axonserver / postgres
axon.event-storage.engine=postgres
Loading