Add data classes and aggregate
Add command and events
This commit is contained in:
parent
fddec51712
commit
4547fb366e
@ -3,8 +3,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
plugins {
|
plugins {
|
||||||
id("org.springframework.boot") version "2.3.3.RELEASE"
|
id("org.springframework.boot") version "2.3.3.RELEASE"
|
||||||
id("io.spring.dependency-management") version "1.0.10.RELEASE"
|
id("io.spring.dependency-management") version "1.0.10.RELEASE"
|
||||||
kotlin("jvm") version "1.3.72"
|
kotlin("jvm") version "1.4.0"
|
||||||
kotlin("plugin.spring") version "1.3.72"
|
kotlin("plugin.spring") version "1.4.0"
|
||||||
|
kotlin("plugin.jpa") version "1.4.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.cubetiqs.demo"
|
group = "com.cubetiqs.demo"
|
||||||
@ -17,9 +18,18 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
implementation("org.axonframework:axon-spring-boot-starter:4.2.1")
|
||||||
|
implementation("io.springfox:springfox-swagger2:2.9.2")
|
||||||
|
implementation("io.springfox:springfox-swagger-ui:2.9.2")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||||
|
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
|
|
||||||
|
runtimeOnly("org.postgresql:postgresql")
|
||||||
|
|
||||||
|
testImplementation("org.axonframework:axon-test:4.2.1")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test") {
|
testImplementation("org.springframework.boot:spring-boot-starter-test") {
|
||||||
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
|
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,123 @@
|
|||||||
package com.cubetiqs.demo.axon
|
package com.cubetiqs.demo.axon
|
||||||
|
|
||||||
|
import com.cubetiqs.demo.axon.command.CreditMoneyCommand
|
||||||
|
import com.cubetiqs.demo.axon.command.DebitMoneyCommand
|
||||||
|
import com.cubetiqs.demo.axon.event.AccountCreatedEvent
|
||||||
|
import com.cubetiqs.demo.axon.event.MoneyCreditedEvent
|
||||||
|
import com.cubetiqs.demo.axon.event.MoneyDebitedEvent
|
||||||
|
import com.cubetiqs.demo.axon.exception.InsufficientBalanceException
|
||||||
|
import org.axonframework.commandhandling.CommandHandler
|
||||||
|
import org.axonframework.eventsourcing.EventSourcingHandler
|
||||||
|
import org.axonframework.modelling.command.AggregateIdentifier
|
||||||
|
import org.axonframework.modelling.command.AggregateLifecycle
|
||||||
|
import org.axonframework.modelling.command.TargetAggregateIdentifier
|
||||||
|
import org.axonframework.spring.stereotype.Aggregate
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||||
import org.springframework.boot.runApplication
|
import org.springframework.boot.runApplication
|
||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.UUID
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.GeneratedValue
|
||||||
|
import javax.persistence.GenerationType
|
||||||
|
import javax.persistence.Id
|
||||||
|
import javax.persistence.Table
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
class AxonApplication
|
class AxonApplication
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
runApplication<AxonApplication>(*args)
|
runApplication<AxonApplication>(*args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
class DefaultController {
|
class DefaultController {
|
||||||
@GetMapping
|
@GetMapping
|
||||||
fun index(): ResponseEntity<Any> {
|
fun index(): ResponseEntity<Any> {
|
||||||
return ResponseEntity.ok("ok")
|
return ResponseEntity.ok("ok")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bank_accounts")
|
||||||
|
data class BankAccount(
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
var id: UUID? = null,
|
||||||
|
|
||||||
|
var owner: String? = null,
|
||||||
|
|
||||||
|
var balance: BigDecimal? = null
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
@Aggregate
|
||||||
|
class BankAccountAggregate(
|
||||||
|
@AggregateIdentifier
|
||||||
|
private var id: UUID? = null,
|
||||||
|
private var balance: BigDecimal? = null,
|
||||||
|
private var owner: String? = null
|
||||||
|
) {
|
||||||
|
@CommandHandler
|
||||||
|
constructor(command: CreateAccountCommand) {
|
||||||
|
AggregateLifecycle.apply(
|
||||||
|
AccountCreatedEvent(
|
||||||
|
command.accountId,
|
||||||
|
command.initialBalance,
|
||||||
|
command.owner
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventSourcingHandler
|
||||||
|
fun on(event: AccountCreatedEvent) {
|
||||||
|
id = event.id
|
||||||
|
owner = event.owner
|
||||||
|
balance = event.initialBalance
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandHandler
|
||||||
|
fun handles(command: CreditMoneyCommand) {
|
||||||
|
AggregateLifecycle.apply(
|
||||||
|
MoneyCreditedEvent(
|
||||||
|
command.accountId,
|
||||||
|
command.creditAmount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventSourcingHandler
|
||||||
|
fun on(event: MoneyCreditedEvent) {
|
||||||
|
balance = balance!!.add(event.creditAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandHandler
|
||||||
|
fun handle(command: DebitMoneyCommand) {
|
||||||
|
AggregateLifecycle.apply(
|
||||||
|
MoneyDebitedEvent(
|
||||||
|
command.accountId,
|
||||||
|
command.debitAmount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventSourcingHandler
|
||||||
|
@Throws(InsufficientBalanceException::class)
|
||||||
|
fun on(event: MoneyDebitedEvent) {
|
||||||
|
if (balance!! < event.debitAmount) {
|
||||||
|
throw InsufficientBalanceException(event.accountId!!, event.debitAmount!!)
|
||||||
|
}
|
||||||
|
balance = balance!!.subtract(event.debitAmount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CreateAccountCommand(
|
||||||
|
@TargetAggregateIdentifier
|
||||||
|
val accountId: UUID? = null,
|
||||||
|
val initialBalance: BigDecimal? = null,
|
||||||
|
val owner: String? = null
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.cubetiqs.demo.axon.command
|
||||||
|
|
||||||
|
import org.axonframework.modelling.command.TargetAggregateIdentifier
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class CreditMoneyCommand(
|
||||||
|
@TargetAggregateIdentifier
|
||||||
|
val accountId: UUID? = null,
|
||||||
|
val creditAmount: BigDecimal? = null
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.cubetiqs.demo.axon.command
|
||||||
|
|
||||||
|
import org.axonframework.modelling.command.TargetAggregateIdentifier
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class DebitMoneyCommand(
|
||||||
|
@TargetAggregateIdentifier
|
||||||
|
val accountId: UUID? = null,
|
||||||
|
val debitAmount: BigDecimal? = null
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.cubetiqs.demo.axon.event
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class AccountCreatedEvent(
|
||||||
|
var id: UUID? = null,
|
||||||
|
var initialBalance: BigDecimal? = null,
|
||||||
|
var owner: String? = null
|
||||||
|
)
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.cubetiqs.demo.axon.event
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class MoneyCreditedEvent(
|
||||||
|
val accountId: UUID? = null,
|
||||||
|
val creditAmount: BigDecimal? = null
|
||||||
|
)
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.cubetiqs.demo.axon.event
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class MoneyDebitedEvent(
|
||||||
|
val accountId: UUID? = null,
|
||||||
|
val debitAmount: BigDecimal? = null
|
||||||
|
)
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.cubetiqs.demo.axon.exception
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class InsufficientBalanceException(accountId: UUID, debitAmount: BigDecimal) : Throwable(
|
||||||
|
"Insufficient Balance: Cannot debit " + debitAmount +
|
||||||
|
" from account number [" + accountId.toString() + "]"
|
||||||
|
)
|
32
src/main/resources/application-dev.yml
Normal file
32
src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
server:
|
||||||
|
port: 8182
|
||||||
|
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driverClassName: org.postgresql.Driver
|
||||||
|
url: jdbc:postgresql://${POSTGRES_HOST:192.168.0.202}:${POSTGRES_PORT:5432}/${POSTGRES_DB:axon_demo}
|
||||||
|
username: ${POSTGRES_USERNAME:cubetiq}
|
||||||
|
password: ${POSTGRES_PASSWORD:Root$}
|
||||||
|
hikari:
|
||||||
|
max-lifetime: 1800000
|
||||||
|
connection-timeout: 30000
|
||||||
|
idle-timeout: 600000
|
||||||
|
maximum-pool-size: 30
|
||||||
|
allow-pool-suspension: true
|
||||||
|
tomcat:
|
||||||
|
max_active: 10
|
||||||
|
max_idle: 5
|
||||||
|
min-idle: 2
|
||||||
|
initial_size: 5
|
||||||
|
remove_abandoned: true
|
||||||
|
jpa:
|
||||||
|
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
show-sql: true
|
||||||
|
hibernate:
|
||||||
|
ddl-auto: update
|
||||||
|
properties:
|
||||||
|
hibernate:
|
||||||
|
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
temp:
|
||||||
|
use_jdbc_metadata_defaults: false
|
||||||
|
open-in-view: true
|
@ -1,2 +1,3 @@
|
|||||||
server:
|
spring:
|
||||||
port: 8182
|
profiles:
|
||||||
|
active: dev
|
Loading…
Reference in New Issue
Block a user