Skip to content
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

Feature/axon example #7

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fff22b7
add a sesond axon example
zambrovski Sep 28, 2022
b30c213
better example aplpication
zambrovski Sep 28, 2022
882c45f
kotlin example with axon onion style added
zambrovski Nov 1, 2022
cf1d4ff
more renaming
zambrovski Nov 1, 2022
862bcb5
add context map
zambrovski Dec 15, 2022
1e45234
improved package layout
zambrovski Dec 15, 2022
0341614
clean archiecture packaging
zambrovski Feb 10, 2023
5c9fd51
implementing clean architecture and write some docs
zambrovski Feb 14, 2023
5bba0b1
Merge branch 'main' into feature/axon-example
zambrovski Feb 14, 2023
233ff50
add more readme
zambrovski Feb 14, 2023
d7b9017
chore: improve pom and package structure, aligned on Tom Hombergs ide…
zambrovski Feb 15, 2023
fc44585
typo
zambrovski Feb 17, 2023
600b1e8
improve domain model, wip
zambrovski Feb 17, 2023
e870c16
improved types, add some unit tests
zambrovski Feb 17, 2023
4574545
domain model test coverage 100
zambrovski Feb 17, 2023
9c52b36
documentation and pics
zambrovski Feb 23, 2023
f719e68
package rename, more diagrams
zambrovski Mar 17, 2023
a64a268
add bpmn saga
jangalinski Mar 21, 2023
4c83891
new diagrams
zambrovski Mar 21, 2023
faf6a56
new image
zambrovski Mar 21, 2023
903eedd
update bpmn
jangalinski Mar 21, 2023
a1018f7
Merge branch 'feature/axon-example' of github.com:holixon/jmolecules-…
jangalinski Mar 21, 2023
9bff094
add images
zambrovski Mar 21, 2023
c1f2580
fun interface & notes
jangalinski Mar 28, 2023
8c3e375
in ports with completable future
janvonneree Mar 30, 2023
1eec233
Merge branch 'main' into feature/axon-example
zambrovski Nov 28, 2023
4842276
update versions, implement improved kotlin annotation detection
zambrovski Nov 28, 2023
51ed660
Domain uses InfrastructureConfiguration and tests are still green ...
p-wunderlich Nov 29, 2023
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
42 changes: 42 additions & 0 deletions jmolecules-axon/01-simple/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jmolecules.examples</groupId>
<artifactId>jmolecules-examples-axon-root</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<name>jMolecules Examples - Axon Framework Simple</name>
<description>Simple Axon Framework Example using JMolecules</description>
<artifactId>jmolecules-axon-simple</artifactId>

<dependencies>
<!-- Axon Framework -->
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-modelling</artifactId>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-eventsourcing</artifactId>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring</artifactId>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.axonframework.queryhandling.QueryHandler;
import org.jmolecules.architecture.cqrs.annotation.QueryModel;
import org.jmolecules.event.annotation.DomainEventHandler;
import org.springframework.stereotype.Component;

@Slf4j
@QueryModel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
ContextMap AxonBank {
type = SYSTEM_LANDSCAPE
state = TO_BE

contains BankAccountContext
}

BoundedContext BankAccountContext {
Application {
Command CreateBankAccountCommand
Command DepositMoneyCommand
Command WithdrawMoneyCommand
Command CancelMoneyTransferCommand
Command CompleteMoneyTransferCommand
Command ReceiveMoneyTransferCommand
Command RequestMoneyTransferCommand
}
Aggregate BankAccount {
Entity BankAccountAggregate {
aggregateRoot
}
DomainEvent BankAccountCreatedEvent
DomainEvent MoneyDepositedEvent
DomainEvent MoneyWithdrawnEvent
DomainEvent MoneyTransferCancelledEvent
DomainEvent MoneyTransferCompletedEvent
DomainEvent MoneyTransferReceivedEvent
DomainEvent MoneyTransferredEvent
DomainEvent MoneyTransferRequestedEvent
}
}

34 changes: 34 additions & 0 deletions jmolecules-axon/02-axonstyle-cqrs-es-bank/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jmolecules.examples</groupId>
<artifactId>jmolecules-examples-axon-root</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<name>jMolecules Examples - Axon Framework Bank Axon-Style/CQRS/ES</name>
<description>Axon Framework Spring-Boot Example using JMolecules applying Onion Architecture and CQRS/ES</description>
<artifactId>jmolecules-axon-style-cqrs-es-bank</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.jmolecules.example.axonframework;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@OpenAPIDefinition
public class AxonBankApplication {

public static void main(String[] args) {
SpringApplication.run(AxonBankApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ApplicationRing
package org.jmolecules.example.axonframework.application;

import org.jmolecules.architecture.onion.simplified.ApplicationRing;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jmolecules.example.axonframework.domain.api.command;

import org.axonframework.modelling.command.TargetAggregateIdentifier;
import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

@Command(namespace = "axon.bank", name = "CreateBankAccountCommand")
public record CreateBankAccountCommand(
@Association
String accountId,
int initialBalance
) {
// empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jmolecules.example.axonframework.domain.api.command.atm;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

@Command(namespace = "axon.bank", name = "DepositMoneyCommand")
public record DepositMoneyCommand(
@Association
String accountId,
int amount
) {
// empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jmolecules.example.axonframework.domain.api.command.atm;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

@Command(namespace = "axon.bank", name = "WithdrawMoneyCommand")
public record WithdrawMoneyCommand(
@Association
String accountId,
int amount
) {
// empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jmolecules.example.axonframework.domain.api.command.transfer;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

@Command(namespace = "axon.bank", name = "CancelMoneyTransferCommand")
public record CancelMoneyTransferCommand(

@Association
String sourceAccountId,

String moneyTransferId,

String reason

) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.jmolecules.example.axonframework.domain.api.command.transfer;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

@Command(namespace = "axon.bank", name = "CompleteMoneyTransferCommand")
public record CompleteMoneyTransferCommand(

@Association
String sourceAccountId,

String moneyTransferId

) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.jmolecules.example.axonframework.domain.api.command.transfer;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

/**
* Invoked by the saga, recipient is target account.
*/
@Command(namespace = "axon.bank", name = "ReceiveMoneyTransferCommand")
public record ReceiveMoneyTransferCommand(
@Association
String targetAccountId,

String moneyTransferId,

int amount
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.jmolecules.example.axonframework.domain.api.command.transfer;

import org.jmolecules.architecture.cqrs.annotation.Command;
import org.jmolecules.ddd.annotation.Association;

/**
* Received by the source account.
* Reserves amount for transfer and starts saga.
*/
@Command(namespace = "axon.bank", name = "RequestMoneyTransferCommand")
public record RequestMoneyTransferCommand(

@Association
String sourceAccountId,

String targetAccountId,

int amount
) {

// empty

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jmolecules.example.axonframework.domain.api.exception;


public class InsufficientBalanceException extends RuntimeException{

public InsufficientBalanceException(String accountId, int currentBalance, int withdrawAmount, int minAmount) {
super(String.format("BankAccount[id=%s, currentBalance=%d]: Withdrawal of amount=%d not allowed, would subceed min. balance of %d",
accountId,
currentBalance,
withdrawAmount,
minAmount
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jmolecules.example.axonframework.domain.api.exception;
public class MaximumBalanceExceededException extends RuntimeException {


public MaximumBalanceExceededException(String accountId, int currentBalance, int depositAmount, int maxAmount) {
super(String.format("BankAccount[id=%s, currentBalance=%d]: Deposit of amount=%d not allowed, would exceed max. balance of %d",
accountId,
currentBalance,
depositAmount,
maxAmount
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.jmolecules.example.axonframework.domain.api.query;

import org.axonframework.messaging.responsetypes.ResponseType;
import org.axonframework.messaging.responsetypes.ResponseTypes;

import java.util.Optional;


public record CurrentBalanceQuery(
String accountId
) {
public static ResponseType<Optional<CurrentBalanceResponse>> RESPONSE_TYPE = ResponseTypes.optionalInstanceOf(CurrentBalanceResponse.class);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.jmolecules.example.axonframework.domain.api.query;

public record CurrentBalanceResponse(
String accountId,
int currentBalance
) {
// empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.jmolecules.example.axonframework.domain.api.query;

public record MoneyTransfer(
String moneyTransferId,
String sourceAccountId,
String targetAccountId,
int amount,
Boolean success,
String message
) {

public MoneyTransfer(String moneyTransferId, String sourceAccountId, String targetAccountId, int amount) {
this(moneyTransferId, sourceAccountId, targetAccountId, amount, null, null);
}

public MoneyTransfer(String moneyTransferId, String sourceAccountId, String targetAccountId, int amount, String message) {
this(moneyTransferId, sourceAccountId, targetAccountId, amount, message == null, message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jmolecules.example.axonframework.domain.api.query;

import org.axonframework.messaging.responsetypes.ResponseType;
import org.axonframework.messaging.responsetypes.ResponseTypes;

import java.util.Optional;

public record MoneyTransferByIdQuery(String moneyTransferId) {

public static final ResponseType<Optional<MoneyTransfer>> RESPONSE_TYPE = ResponseTypes.optionalInstanceOf(MoneyTransfer.class);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jmolecules.example.axonframework.domain.api.query;

import org.axonframework.messaging.responsetypes.ResponseType;
import org.axonframework.messaging.responsetypes.ResponseTypes;

public record MoneyTransfersQuery(String accountId) {
public static final ResponseType<MoneyTransfersResponse> RESPONSE_TYPE = ResponseTypes.instanceOf(MoneyTransfersResponse.class);

public MoneyTransfersQuery() {
this(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jmolecules.example.axonframework.domain.api.query;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public record MoneyTransfersResponse(List<MoneyTransfer> moneyTransfers) {

public MoneyTransfersResponse(Collection<MoneyTransfer> moneyTransfers) {
this(new ArrayList<>(moneyTransfers));
}
}
Loading