Skip to content

Simple Kotlin and Java command/query bus

License

Notifications You must be signed in to change notification settings

nbottarini/cqbus-kt

Repository files navigation

CQBus

 

Simple Kotlin and Java command/query bus

Maven License: MIT CI Status

Installation

Gradle (Kotlin)

repositories {
    mavenCentral()
}

dependencies {
    implementation("dev.botta:cqbus:1.2.0")
}

Gradle (Groovy)

repositories {
    mavenCentral()
}

dependencies {
    implementation 'dev.botta:cqbus:1.2.0'
}

Maven

<dependency>
    <groupId>dev.botta</groupId>
    <artifactId>cqbus</artifactId>
    <version>1.2.0</version>
</dependency>

Usage

Commands

class CreateFullName(val firstName: String, val lastName: String): Command<String>

class CreateFullNameHandler: RequestHandler<CreateFullName, String> {
    override fun execute(request: CreateFullName, identity: Identity): String {
        return request.firstName + " " + request.lastName
    }
}

val cqBus = CQBus()
cqBus.registerHandler { CreateFullNameHandler() }

cqBus.execute(CreateFullName("John", "Doe")) // returns "John Doe"

Queries

class GetNews: Query<List<String>>

class GetNewsHandler: RequestHandler<GetNews, List<String>> {
    override fun execute(request: GetNews, identity: Identity): List<String> {
        return listOf("news 1", "news 2")
    }
}

val cqBus = CQBus()
cqBus.registerHandler { GetNewsHandler() }

cqBus.execute(GetNews()) // returns "news 1", "news 2"

Execution Identity

class UserIdentity(override val name: String): Identity {
    override val isAuthenticated = true
    override val authenticationType: String? = null
    override val roles = listOf<String>()
    override val properties = mapOf<String, Any>()
}

class MyCommand: Command<String>

class MyCommandHandler: RequestHandler<MyCommand, String> {
    override fun execute(request: MyCommand, identity: Identity): String {
        return identity.name
    }
}

val cqBus = CQBus()
cqBus.registerHandler { MyCommandHandler() }

cqBus.execute(MyCommand(), ExecutionContext().withIdentity(UserIdentity("Alice"))) // returns "Alice"
cqBus.execute(MyCommand()) // returns "Anonymous"

Context-aware handlers

class MyCommand: Command<String>

class MyCommandHandler: ContextAwareRequestHandler<MyCommand, String> {
    override fun execute(request: MyCommand, context: ExecutionContext): String {
        return context["some-key"] as String
    }
}

val cqBus = CQBus()
cqBus.registerHandler { MyCommandHandler() }

cqBus.execute(MyCommand(), ExecutionContext().with("some-key", "some-value")) // returns "some-value"

Middlewares

class MyCommand: Command<String>

class MyCommandHandler: RequestHandler<MyCommand, String> {
    override fun execute(request: MyCommand, identity: Identity): String {
        return "handler"
    }
}

class LoggingMiddleware(private val log: MutableList<String>, private val suffix: String = ""): Middleware {
    override fun <T: Request<R>, R> execute(request: T, next: (T) -> R, context: ExecutionContext): R {
        log.add("before$suffix")
        val result = next(request)
        log.add("after$suffix")
        return result
    }
}

val log = mutableListOf<String>()
val cqBus = CQBus()
cqBus.registerHandler { MyCommandHandler() }
cqBus.registerMiddleware(LoggingMiddleware(log, "1"))
cqBus.registerMiddleware(LoggingMiddleware(log, "2"))

cqBus.execute(MyCommand())

// log contains "before2", "before1", "handler", "after1", "after2"

Middleware registration by priority

val log = mutableListOf<String>()
val cqBus = CQBus()
cqBus.registerHandler { MyCommandHandler() }
cqBus.registerMiddleware(LoggingMiddleware(log, "Low"), MiddlewarePriorites.Low)
cqBus.registerMiddleware(LoggingMiddleware(log, "VeryHigh1"), MiddlewarePriorities.VeryHigh)
cqBus.registerMiddleware(LoggingMiddleware(log, "VeryHigh2"), MiddlewarePriorities.VeryHigh)
cqBus.registerMiddleware(LoggingMiddleware(log, "Normal"))

cqBus.execute(MyCommand())

// log contains:
//   "beforeVeryHigh2", 
//   "beforeVeryHigh1", 
//   "beforeNormal", 
//   "beforeLow", 
//   "handler", 
//   "afterLow", 
//   "afterNormal",
//   "afterVeryHigh1",
//   "afterVeryHigh2",

About

Simple Kotlin and Java command/query bus

Resources

License

Stars

Watchers

Forks

Languages