An implementation of MediatR on JVM for Spring using Kotlin coroutines

Overview

Kpring MediatR License: MIT

In this project, an attempt has been made to implement the mediator pattern on the JVM with simplicity using Kotlin with native coroutine support for the Spring Framework and is heavily inspired by the MediatR project for .NET by Jimmy Bogard.

Everything's going asynchronously with using Kotlin coroutine features.

Kotlin MediatR can be used in both reactive-programming style and Kotlin native coroutine. is also intended to help developers be more focused on their code and write cleaner and decoupled components

Requirements

  • Java 8 +
  • Spring Framework 5 / Spring Boot 2*

Setup and Configuration

To get the Kpring-MediatR, you can use both GitHub and Maven Central Repositories. To use Maven Central, do the following:

Maven
<dependency>
  <groupId>io.github.mahdibohloul</groupId>
  <artifactId>kpring-mediatR-starter</artifactId>
  <version>v1.0.0</version>
</dependency>
Gradle
implementation("io.github.mahdibohloul:kpring-mediatR-starter:v1.0.0")

To set up and config Kpring mediator in your project add the bean to your project as follows:

@Configuration
class MediatorConfiguration(
    @Autowired val applicationContext: ApplicationContext
) {

    @Bean
    fun factory(): Factory {
        return DefaultFactory(applicationContext)
    }

    @Bean
    fun mediator(factory: Factory): Mediator {
        return DefaultMediator(factory)
    }
}

Features

Kpring Mediator offers three types of features:

Request:

You send a request to anyone who can handle the request, and the handler prepares the response you want. Note that there can only be one request handler per request.

Command:

Like Request, you send a command to anyone who can handle the command, except that you will not receive a response. Also, there can only be one command handler per command.

Notification:

You publish a notification and the relevant handlers receive the notification and do something about it. It is useful when something special is happening in your system and you want to do separate tasks in parallel afterwards. For example, when a shipment is cancelled, you may want to send an email to the order owner and the driver and vendor of the shipment that is not related to your main process, to do this you can publish a notification.

Usage

Do not forget to use the component annotation with your handler. it helps the mediator to register your handlers.

Request usage

class GetCustomerByUsernameRequest(val username: String?) : Request<Customer?>
@Component
class GetCustomerByUsernameRequestHandler(
    @Autowired val customerRepository: CustomerRepository
) : RequestHandler<GetCustomerByUsernameRequest, Customer?> {
    override suspend fun handle(request: GetCustomerByUsernameRequest): Customer? {
        return customerRepository.findFirstByUsername(request.username).awaitFirstOrNull()
    }
}

Command usage

class CancelOrderCommand(val order: Order) : Command
@Component
class CancelOrderCommandHandler : CommandHandler<CancelOrderCommand> {
    override suspend fun handle(command: CancelOrderCommand) {
        //Cancellation process
    }
}

Notification usage

class OrderCancelledNotification : Notification
@Component
class OrderCancelledNotificationHandler : NotificationHandler<OrderCancelledNotification> {
    override suspend fun handle(event: OrderCancelledNotification) {
        //Do something
    }
}

@Component
class SendEmailToVendorWhenOrderCancelledNotificationHandler : NotificationHandler<OrderCancelledNotification> {
    override suspend fun handle(event: OrderCancelledNotification) {
        //Send email to vendor
    }
}

Use in reactive style

Add the Kotlinx coroutines reactor to your project.

@Service
class ProductService(
    @Autowired val mediator: Mediator
) {
    fun reserveProduct(): Mono<Boolean> {
        val request = GetCustomerByUsernameRequest("username")
        mono { mediator.sendAsync(request) }.map {
            if (it?.username?.isEmpty()!!)
                throw CustomerDoesntExistsException()
            return@map it
        } //DO SOMETHING
    }
}

Exceptions

There are 5 different exceptions: NoRequestHandlerException, DuplicateRequestHandlerRegistrationException, NoNotificationHandlersException, NoCommandHandlerException, DuplicateCommandHandlerRegistrationException, all of each are inherited from KpringMediatorException.

Exceptions that occur in request handlers and command handlers were propagated in the parent and canceled the process, but if an exception occurs in one of the notification handlers, it is ignored and the other notification handlers continue to operate.

I am currently working on a system for logging exceptions that occur in specific notification handlers, and I hope to improve this in later versions.

If you can improve this project, do not hesitate to contribute with me. I'm waiting for your merge requests with open arms.

You might also like...
A sample skeleton backend app built using Spring Boot kotlin, Expedia Kotlin Graphql, Reactive Web that can be deployed to Google App Engine Flexible environmennt

spring-kotlin-gql-gae This is a sample skeleton of a backend app that was built using: Spring Boot(Kotlin) Reactive Web Sprinng Data R2DBC with MYSQL

API for a library using Kotlin, Spring-boot and covered by test

Library API This API is to create Books and be able to borrow from them I'm using: Spring Boot version 2.5.6 Kotlin 1.5.31 Java 11 I'm implementing us

Push notification application using One Signal + Spring Boot + Kotlin

Spring Boot push notification system using One Signal This project was created to demonstrate a simple application built with Kotlin + Spring Boot inc

In this Repo i create public apis to serve apps, like muslim apps using Spring, kotlin, and microservices

spring-freelance-apis-kotlin In this Repo i create public apis to serve apps, like muslim apps using Spring, kotlin, and microservices This repo for l

Spring Boot built using Kotlin, H2, Postgres, Hibernate and JPA

Spring-Boot-Kotlin-Sample Spring Boot built using Kotlin, H2, Postgres, Hibernate and JPA Getting Started Reference Documentation For further referenc

Microservices-demo - Microservices demo project using Spring, Kotlin, RabbitMQ, PostgreSQL and Gradle and deployed to Azure Kubernetes
Grocery - A simple CRUD Project using Spring Boot, Kotlin and MongoDB

Grocery - A simple CRUD Project using Spring Boot, Kotlin and MongoDB

A complete Kotlin application built to demonstrate the use of Modern development tools with best practices implementation using multi-module architecture developed using SOLID principles
A complete Kotlin application built to demonstrate the use of Modern development tools with best practices implementation using multi-module architecture developed using SOLID principles

This repository serves as template and demo for building android applications for scale. It is suited for large teams where individuals can work independently on feature wise and layer wise reducing the dependency on each other.

Collection of JVM library logic that the Sirloin software development team is currently using

Collection of JVM library logic that the Sirloin software development team is currently using

Comments
  • Notification error handling

    Notification error handling

    Implement NotificationExceptionHandler

    • Define new notification error handling feature to Kpring
    • Change README with new features
    • Change version to 1.1.0
    enhancement 
    opened by mahdibohloul 0
Releases(1.1.0)
  • 1.1.0(Feb 9, 2022)

    Add notification exception handling feature Now your can handle thrown exceptions inside the notification handling process in another way!

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Dec 4, 2021)

    What's Changed

    • Add dispatcher to the notification handler by @mahdibohloul in https://github.com/mahdibohloul/Kpring-mediatR/pull/13
    • Use a specific dispatcher for every notification handler to dispatch on a specific thread.

    Full Changelog: https://github.com/mahdibohloul/Kpring-mediatR/compare/1.0.0...1.0.1

    Source code(tar.gz)
    Source code(zip)
Owner
Mahdi Bohloul
Back-End developer at Tap30
Mahdi Bohloul
Spring-kotlin - Learning API Rest with Kotlin, Spring and PostgreSQL

Kotlin, Spring, PostgreSQL and Liquibase Database Migrations Learning Kotlin for

Andre L S Ferreira 2 Feb 14, 2022
Simple Todo list API using Spring-Boot, Webflux, Kotlin, Coroutines, & PostgreSQL

Simple Todo list API using Spring-Boot, Webflux, Kotlin, Coroutines, & PostgreSQL

Sami Eljabali 9 Jul 26, 2022
Asynchronous Spring Initializr API wrapper for Kotlin/JVM

initializr-kt Asynchronous Spring Initializr API wrapper for Kotlin/JVM. This library provides the simplest DSL for initializing Spring Boot projects

Mikhail Titov 2 May 8, 2022
Reactive setup with Spring WebFlux , Kotlin, Postgres and Spring Data R2DBC

Reactive Spring with Kotlin and Pg Spring WebFlux with Netty instead of Spring Web with Tomcat Mono and Flux in all layers (controller, service, repo)

Bimal Raj Gyawali 7 Dec 9, 2022
Example of using coroutines with Spring MVC

This is an example of using coroutines with Spring MVC (not webflux!) DemoController uses https://github.com/joost-de-vries/spring-coroutine, but sinc

Tiberiu Tofan 4 Dec 9, 2022
This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

Maksim Kostromin 2 Nov 29, 2021
Spring-with-maven - Spring Boot App with Postgresql and maven

Spring Boot Api Aplikasi ini dibuat menggunakan bahasa kotlin dan untuk database

Aldi Aulia Rosyad 1 Jan 12, 2022
Android login spring - Android login against spring backend

Android Jetpack Compose login implementation with JWT tokens against our own bac

null 1 Feb 13, 2022
Saga pattern implementation in Kotlin build in top of Kotlin's Coroutines.

Module Saga Website can be found here Add in build.gradle.kts repositories { mavenCentral() } dependencies { implementation("io.github.nomisr

Simon Vergauwen 50 Dec 30, 2022
Archimedes's implementation for the Java Virtual Machine (JVM)

Archimedes Give me a place to stand, and I shall move the earth. Archimedes's implementation for the Java Virtual Machine (JVM) Building From Source T

Archimedes 24 Aug 20, 2022