# Messaging Framework

## Overview

Blueprint has a built-in messaging framework that helps you to design a reactive application. The messaging framework is similar to [events in Node.js](https://nodejs.org/api/events.html), but events are handled asynchronously by default. This design approach allows controllers to fire off events without waiting for background tasks to complete—returning control as quick as possible to the client.

{% hint style="info" %}
The messaging framework consists of [messengers](https://github.com/onehilltech/blueprint/wiki/Application%3AMessaging#sending-messages-to-listeners) and [listeners](https://github.com/onehilltech/blueprint/wiki/Application%3AMessaging#defining-listeners-to-receive-messages).
{% endhint %}

## Object Events

The `BaseObject` class (see [The Object Model](/developer-guide/the-object-model.md)) has methods for emitting and consuming events specific to the corresponding object instance. To emit an event from the object, use the `emit(...args)` method. Use either the `once(name, ...args)` or `on(name, ...args)` method to consume the corresponding event a single time or any time it is emitted, respectively. Here is an example for emitting and consuming an event on an object.

```javascript
const { BO } = require ('@onehilltech/blueprint');

const Connection = BO.extend ({
  open (opts) {
    // do something..
    
    this.emit ('opened', this);
  }
});

// ...

let conn = new Connection ();
conn.on ('opened', conn => {
  console.log ('The connection is open');
});
```

As shown in the example above, the `Connection.open()` method emits the opened event on the object instance. We can then register to receive the event, which is illustrated with we call the `conn.on()` method. You can also use the `conn.once()` if you only want to listener to be notified once when a connection is opened, and not every time the connection is opened.

## Application Events

Application events are events emitted through the Blueprint application. This should not be confused with the actual application event types. Unlike the [object events discussed above](/developer-guide/untitled.md#object-events), the implementation logic for both application emitters and consumers is different.

### Implementing a Listener

All application event listeners are implemented in `app/listeners/[EVENT_NAME]` were `EVENT_NAME` is the name of the event you are listening. The application event listeners must also extend the `Listener` class in Blueprint. Here is an example of an application event listener responding to connection open events.

{% code title="app/listeners/conn.open/console.js" %}

```javascript
const { Listener } = require ('@onehilltech/blueprint');

module.exports = Listener.extend ({
  handleEvent (conn) {
    console.log ('The connection is open');
  }
});
```

{% endcode %}

The event listener must implement the `handleEvent()` method. Similar to the object events, the `handleEvent()` method takes a variable number of parameters. This count depends on the number of parameters passed to the `emit()` method.

### Emitting an Event

You emit an application event in a similar manner as emitting object events. The main different is you use `blueprint.emit()` method instead of directly emitting on the local object instance. Here is an example emitting the connection open event as an application event.

```javascript
const blueprint = require ('@onehilltech/blueprint'); 
const { BO } = blueprint;

const Connection = BO.extend ({
  open (opts) {
    // do something..
    
    this.emit ('opened', this);
    blueprint.emit ('conn.opened', this);
  }
});
```

As shown in this example, the first `emit()` method is publishing the event a local object instance. The second `emit()` is publishing the event on through the Blueprint application.

### The Application Instance

If you are implementing a Blueprint entity, such as a [controller](/developer-guide/routers-and-controllers/controllers.md), [listener](/developer-guide/untitled.md#implementing-a-listener), or [policy](/developer-guide/policies.md),  then you have access to the application instance as a data property. If you already have direct access to the application class, then you do not need to use `blueprint.emit()` and `blueprint.on()` or `blueprint.once()` to send and receive application events. Instead, you can use the `emit()`, `once()`, and `on()` method on the application instance.

### Predefined Events

The following events are predefined to the Blueprint application.

* `blueprint.app.init` - Called after the application is initialized.
* `blueprint.app.started` - Called after the application is started.

## Inter-Module Communication

One key feature of the messaging framework is entities can communicate with listeners in different [Blueprint modules](/developer-guide/untitled-1.md). We call this *inter-module communication*. This allows modules to be loosely coupled with other modules in an application. It also allows listening modules to react to module events without the source module knowing the listening module is dependent on its behavior.

## Synchronous Messaging

### Emitters

By default, emitting an event is an asynchronous operation. This means the client does not wait for all listeners to process the event before continuing. To make event processing a synchronous operation,  the client to wait for the event to be processed. You do this by waiting for the `Promise` returned from the `emit()` method to be resolved.

```javascript
conn.emit ('opened', this);                     // asynchronous

conn.emit ('opened', this).then (() => {        // synchronous

});
```

### Listeners

The listener also can be asynchronous. If the listener is performing background processing, then it can return a `Promise`. If the emitter is asynchronous, then it will not continue until the listener's promise is either resolved or rejected.

```javascript
const { Listener } = require ('@onehilltech/listener');

module.exports = Listener.extend ({
  handleEvent (conn) {
    return new Promise ((resolve, reject) => {
      // Add background processing code here
    });
  }
});
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blueprint.onehilltech.com/developer-guide/untitled.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
