Home / Intel Hub / Dossier

[STATUS: ANONYMOUS] • [ENCRYPTION: AES-256-GCM] • [NODES: 14 ACTIVE] • [LEGACY: 13 YEARS] • [LOCATION: HIDDEN] • [OPERATOR: MASTER]
Services Intel Hub About Contact
[BACK TO HUB] / DOSSIER: emissary-a-fast-open-source-java-messaging-library-vE78I

Emissary, a fast open-source Java messaging library

Status ACTIVE_INTEL
Intel Node GITHUB.COM
Read Time 5 MIN_SCAN
Protocol V12.2_SYNC
Tactical Profile Identified
[TARGET] META
[TARGET] GITHUB
[TECH] AI
[TECH] GO
EXTRACTED FROM: https://github.com/joel-jeremy/emissary

Emissary (formerly Deezpatch)

Like the project?

Get Emissary

Gradle

source
implementation "io.github.joel-jeremy.emissary:emissary-core:${version}"
Emissary (formerly Deezpatch) A simple-to-use, no dependency, yet 🗲BLAZING FAST🗲 messaging library for decoupling messages (requests and events) and message handlers 🚀 Emissary aims to take advantage of the simplicity of using the annotations for handlers (e.g. @RequestHandler/@EventHandler) without the drawbacks of reflection (slow). Emissary aims to make it easy to build applications that apply the Command Query Responsibility Segregation (CQRS) pattern, but it is not in any way limited to that pattern only. Like the project? Please consider giving the repository a ⭐. It means a lot! Thank you :) Get Emissary Important Up until v1.1.0, the core library is published under the old deezpatch-core name. This has been renamed to emissary-core starting from v2.0.0 onwards. Gradle implementation "io.github.joel-jeremy.emissary:emissary-core:$" Maven <dependency> <groupId>io.github.joel-jeremy.emissary</groupId> <artifactId>emissary-core</artifactId> <version>$</version> </dependency> Java 9 Module Names Important Up until v1.1.0, the core library has the module name io.github.joeljeremy.deezpatch.core. This has been renamed to io.github.joeljeremy.emissary.core starting from v2.0.0 onwards. Emissary jars are published with Automatic-Module-Name manifest attribute: Core - io.github.joeljeremy.emissary.core Module authors can use above module names in their module-info.java: module foo.bar Performance What differentiates Emissary from other messaging/dispatch libraries? It takes advantage of java.lang.invoke.LambdaMetafactory to avoid the cost of invoking methods reflectively. This results in performance close to directly invoking the request handler and event handler methods! ~ 1000% more throughput compared to other similar libraries (Spring's ApplicationEventPublisher, Pipelinr, EventBus) ~ 90% faster compared to other similar libraries (Spring's ApplicationEventPublisher, Pipelinr, EventBus) Java 25 Benchmarks Java 21 Benchmarks Java 17 Benchmarks Java 11 Benchmarks Requests Requests are messages that either: Initiate a state change/mutation Commands in CQRS Retrieve/query data Queries in CQRS public class CreateFooCommand implements Request<Void> public String name() } public class GetFooByNameQuery implements Request<Foo> public String name() } Request Handlers Requests are handled by request handlers. Request handlers can be registered through the use of the @RequestHandler annotation. A request must only have a single request handler. (@RequestHandlers fully support methods with void return types! No need to set method return type to Void and return null for no reason.) public class CreateFooCommandHandler } public class GetFooQueryHandler } Request Dispatcher Requests are dispatched to a single request handler and this can be done through a dispatcher. public static void main(String[] args) Events Events are messages that indicate that something has occurred in the system. public class FooCreatedEvent implements Event public String name() } Event Handlers Events are handled by event handlers. Event handlers can be registered through the use of the @EventHandler annotation. An event can have zero or more event handlers. public class FooEventHandler @EventHandler public void notifyB(FooCreatedEvent event) } Event Publisher Events are dispatched to zero or more event handlers and this can be done through a publisher. public static void main(String[] args) Easy Integration with Dependency Injection (DI) Frameworks The library provides an InstanceProvider interface as an extension point to let users customize how request/event handler instances should be instantiated. This can be as simple as new-ing up request/event handlers or getting instances from a DI framework such as Spring's ApplicationContext, Guice's Injector, etc. Example with No DI framework // Application.java public static void main(String[] args) private static Object getInstance(Class<?> handlerType) else if (MyEventHandler.class.equals(handlerType)) throw new IllegalStateException("Failed to get instance for " + handlerType.getName() + "."); } Example with Spring's ApplicationContext public static void main(String[] args) Example with Guice's Injector public static void main(String[] args) Custom Request/Event Handler Annotations In cases where a project is built in such a way that bringing in external dependencies is considered a bad practice (e.g. domain layer/package in a Hexagonal (Ports and Adapters) architecture), Emissary provides a way to use custom request/event handler annotations (in addition to the built-in RequestHandler and EventHandler annotations) to annotate request/event handlers. This way, Emissary can still be used without adding the core Emissary library as a dependency of a project's domain layer/package. Instead, it may be used in the outer layers/packages to wire things up. // Let's say below classes are declared in a project's core/domain package: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AwesomeRequestHandler @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AwesomeEventHandler public class MyRequestHandler } public class MyEventHandler } // To wire things up: public static void main(String[] args) Custom Invocation Strategies The library provides Emissary.RequestHandlerInvocationStrategy and Emissary.EventHandlerInvocationStrategy interfaces as extension points to let users customize how request/event handler methods are invoked by the Dispatcher and Publisher. Built-in implementations are: SyncRequestHandlerInvocationStrategy (Default) SyncEventHandlerInvocationStrategy (Default) AsyncEventHandlerInvocationStrategy Users can create a new implementation and override the defaults by: // Register custom invocation strategy. Emissary emissary = Emissary.builder() .requests(config -> c...
0 Acknowledgements