Skip to content
/ jsms Public

A lightweight implementation of a messaging framework for JavaScript/TypeScript (inspired by the Java™ Message Service API)

License

Notifications You must be signed in to change notification settings

rfruesmer/jsms

Repository files navigation

JavaScript Message Service

npm Version Build Status Coverage Status Total alerts Language grade: JavaScript

A lightweight implementation of a messaging framework for JavaScript/TypeScript - inspired by the Java™ Message Service API.

Contents

Introduction

Overview

jsms provides a common way for JavaScript programs to create, send and receive messages. It defines some messaging semantics and a corresponding set of JavaScript classes to build clients, servers and even message brokers using a single, unified message API. It was initially developed to eliminate boilerplate code by combining two partly redundant messaging solutions into one.

It can be used right out of the box in terms of an in-process mediator/event bus, but for connecting to a JMS broker or for using protocols/transports like for example STOMP over WebSocket, you can do so by supplying a custom connection class that integrates your own or other (3rd-party) communication implementations - see the simple HTTP-based sample implementation inside the examples folder for a starting point.

What jsms does not include

  • Specific communication protocols

  • A complete implementation of the Java™ Message Service API specs, since jsms targets a simplified and more lightweight approach

  • A threading/worker model (at least not for now) - therefore all send/receive functions are asynchronous by nature (using promises)

Message Model

Messages

jsms messages are composed of the following parts:

  • Header - contains values used by both clients and providers to identify and route messages

  • Body - jsms defines only one type being any custom object literal

Message header fields

id the id header field contains a value that uniquely identifies each message (uuid)
destination the topic or queue name
expiration the time in milliseconds when this message will expire or zero if the message shouldn't expire
correlationID used for matching replies/responses to original message

Messaging domains

jsms supports both major styles of messaging: Point-to-point (PTP) and Publish/subscribe (pub/sub).

Point-to-point model

Use PTP messaging when every message you send must be processed successfully by one consumer:

  • Each queue/message has only one consumer.

  • A sender and a receiver of a message have no timing dependencies. The receiver can fetch the message whether or not it was running when the client sent the message.

  • Queues retain all (up to maxSize) messages sent to them until the messages are consumed, the message expires or the queue is closed - messages aren't persisted.

An application may send messages to a queue by using a connection's QueueSender object. Messages can be consumed from a queue by using a connection's QueueReceiver object.

The JsmsService facade class provides a simplified API for both send and receive operations.

Publish/subscribe model

Topics take care of distributing the messages arriving from multiple publishers to its multiple subscribers:

  • Topics retain messages only as long as it takes to distribute them to current subscribers.

  • Each message may have multiple consumers.

  • Publishers and subscribers have a timing dependency. A client that subscribes to a topic can consume only messages published after the client has created a subscription.

An application may send messages to a topic by using a connection's TopicPublisher object. Messages can be consumed from a topic by using a connection's TopicSubscriber object.

The JsmsService facade class provides a simplified API for both publish and subscribe operations.

Compatibility

Node.js 10.x or later (using CommonJS module format)
Browsers any ES6-compatible, tested with Chrome 76 and Firefox 68

Installation

In your project root:

$ npm install jsms

To enable logging, you have to include a log4js compliant framework like log4js-node - if no version of log4js can be found, then jsms simply does not output anything.

Important note for webpack users: if you don't use log4js, it must be excluded via module.noParse, otherwise you will run into an unresolved module dependency error.

For help with integrating jsms into your project, please refer to the bare-bones examples in the following repos:

Examples using the simplified API

These are just a few simple examples to give you a quickstart. For further information, please refer to the JSDoc comments, annotated tests and the examples folder.

Point-to-Point

const messageService = new JsmsService();

messageService.send("/some/queue", {abc: "xyz"})
    .then(response => {
        console.log(response.body); // expected output: {xyz: "abc"}
    });

messageService.receive("/some/queue")
    .then(message => {
        console.log(message.body); // expected output: {abc: "xyz"}
        return {xyz: "abc"};
    });

Chaining

JsmsService intercepts chained thens for point-to-point sends/receives to provide a more logical flow. This shouldn't encourage anybody to create fine-grained chatty interfaces, but might be useful sometimes and definitely is something notable since it differs from the expected promise default behavior:

const messageService = new JsmsService();

messageService.send("/some/queue", {request: "PING1"})
    .then(response => {
        console.log(response.body); // expected output: {response: "PONG1"}
        return {request: "PING2"};
    })
    .then(response => {
        console.log(response.body); // expected output: {response: "PONG2"}
    });

messageService.receive("/some/queue")
    .then(request => {
        console.log(request.body); // expected output: {request: "PING1"}
        return {response: "PONG1"};
    })
    .then(request => {
        console.log(request.body); // expected output: {request: "PING2"}
        return {response: "PONG2"};
    });

Publish/Subscribe

const messageService = new JsmsService();

messageService.subscribe("/some/topic", message => {
    console.log(message.body); // expected output: {xyz: "abc"}
});

messageService.publish("/some/topic", {xyz: "abc"});

Contributing

Please keep in mind that this project is still in beta state, but if you find something important missing or not working right in your use case, don't hesitate and feel free to open an issue or to send me a pull request.

Credits

@log4js-node/log4js-api homepage  -  show license
uuid homepage  -  show license

License

MIT

About

A lightweight implementation of a messaging framework for JavaScript/TypeScript (inspired by the Java™ Message Service API)

Resources

License

Stars

Watchers

Forks

Packages

No packages published