Introducing Zowe Client’s Event-Driven Architecture

Amber Torrise
Zowe
Published in
5 min readSep 10, 2024

{Core} The Open Mainframe Project’s Zowe CLI squad is excited to introduce a new feature set within our event-driven architecture: the Event Operator and Event Processor. These classes are part of the Zowe Software Development Kit (SDK) for developers building Zowe extensions to streamline how applications coordinate, watch, and respond to events. This provides a clean way for applications to interact and build a fluid and responsible user experience across the client experience.

These new features will be introduced in the upcoming Zowe V3 release, scheduled for general availability in September 2024, when it will become the long-term support offering.

Why is this Useful?

In complex systems, coordinating actions and state changes across different components can be challenging. This feature set simplifies such tasks by allowing applications within your Zowe Client ecosystem to emit and watch for events seamlessly.

A Tangible Example

Imagine Zowe Explorer wants to subscribe to Zowe events:

  1. Zowe Explorer requests an EventProcessor instance with “watch” permissions for Zowe events from the EventOperator.
  2. Zowe Explorer subscribes to the user event, onVaultChanged , with a callback to display that this change in password was observed.
  3. Whenever the user changes their password in either Zowe Explorer or the Zowe CLI, this change will trigger the previously specified callback.
/*
Zowe Explorer application subscribing to changed password Zowe event:
*/
const zoweWatcher = EventOperator.getWatcher('Zowe');
zoweWatcher.subscribeUser('onVaultChanged', (number) => {
console.log(`Zowe password changed`);
});

What Does It Mean to Emit an Event?

Emitting an event is akin to broadcasting a message. When an application emits an event, it signals that something significant has occurred, such as a user action or a system update. This broadcast is picked up by any part of the application or other applications that are interested in that specific event.

Why Emit an Event?

A application might emit an event to:

  • Notify other components or applications about a change in state.
  • Trigger specific actions in response to user interactions.
  • Facilitate real-time updates and synchronization.

What Does It Mean to Subscribe to an Event?

Subscribing to an event means that an application registers a callback function to be executed when a specific event occurs. This enables applications who are subscribed to and therefore watching an event to react dynamically once the event occurs.

Why Subscribe?

An application might subscribe to an event to:

  • Respond to user actions, such as clicks or form submissions.
  • Update the user interface in response to data changes.
  • Log significant occurrences for monitoring and debugging purposes.

The Role of the Event Operator and Event Processor

Event Operator

The EventOperator is a central component that manages event processors and sets limits on their behavior. It categorizes processors into three types:

  • Watcher: Listens for events and triggers callbacks when events occur.
  • Emitter: Emits events that other applications listen for.
  • EmitterAndWatcher: Combines the functionalities of both watcher and emitter.

Applications use the EventOperator to obtain the appropriate EventProcessor based on their needs. For example, an application might use a watcher to react to user actions and an emitter to notify other components of state changes.

Event Processor

An EventProcessor handles three main functionalities:

  • Subscribing to Events: Registering a callback function that will be executed when the event occurs.
  • Emitting Events: Broadcasting events to notify other parts of the application or other applications.
  • Managing Event Subscriptions: Mapping subscribed events and their corresponding callbacks, ensuring that events are properly handled and dispatched.

How to Use the Event Operator and Event Processor

Acquiring a Processor

Applications must first acquire their processors through the EventOperator:

  • Watcher: Use EventOperator.getWatcher(validAppName) to retrieve a watcher-only event processor. Calling getWatcher() without an app name will return a watcher that defaults to watching the Zowe CLI for events.
  • Emitter: Use EventOperator.getEmitter(validAppName) to retrieve an emitter-only event processor.
  • EmitterAndWatcher: Use EventOperator.getProcessor(validAppName) to retrieve a processor capable of both emitting and watching events.

Note: Processors that include emitting features are restricted from being used with predefined, internal Zowe CLI and Zowe Explorer events.

Using a Processor

Once an application has acquired an EventProcessor, it can:

  • Subscribe to Events: Register callback functions to handle specific events.
  • Emit Events: Broadcast events to notify other parts of the application or other applications.
  • Manage Subscriptions: Ensure that events are properly handled and dispatched.

Tying Processors to App Names

Processors are tied to application names to prevent event collisions and maintain a clear separation of event domains. Valid app names are defined by the list of extenders, ~/.zowe/extenders.json, using the Zowe CLI plug-in or Zowe Explorer extension key-names in this list as the names for their respective processors.

Understanding Event Types

Shared vs User Events

User events are triggered by actions directly related to user interactions or specific user activities. Shared events are relevant to multiple users of a shared system and need to be accessible by various components or services.

Predefined Zowe Events

Zowe provides a set of predefined shared and user events that can be watched. These events can be found in the Zowe CLI GitHub.

Custom Events

Applications can define their own shared and user events, allowing for custom event-driven behavior. This flexibility enables developers to tailor the event system to their specific needs.

Event-Driven Architecture in Action

First, retrieve the list of supported applications from ~/.zowe/extenders.json:

EventUtils.getListOfApps();
// Output: [sampleEmitterApp, sampleAppToNotify, Zowe]

Note: The Zowe app corresponds to events from both Zowe Explorer and Zowe CLI and is included in this list by default.

Second, create processors to emit and listen for events:

//Events of different types to subscribe to:
const eventZoweUser = "onVaultChanged";
const eventZoweShared = "onCredentialManagerChanged";
const eventExtenderUser = "fakeExtenderUserEvent";
const eventExtenderShared = "fakeExtenderSharedEvent";

//Emitter processor instantiation:
const extenderEmitter = EventOperator.getEmitter("extenderEmitterApp");

//Watcher processor instantiation:
const extenderWatcher = EventOperator.getWatcher("extenderEmitterApp");
const zoweWatcher = EventOperator.getWatcher(); //defaults to 'Zowe'

//Subscribe: set up callbacks for watchers
extenderWatcher.subscribeShared(eventExtenderShared, callback);
extenderWatcher.subscribeUser(eventExtenderUser, callBackToTrigger);
zoweWatcher.subscribeShared(eventZoweShared, callback);
zoweWatcher.subscribeUser(eventZoweUser, [callback1, callback2]);

//Emit: broadcast an event
extenderEmitter.emitEvent(eventExtenderUser);
/*
Emitting the extender's user event will trigger the subscribed
callback function, `callBackToTrigger`, on the extenderWatcher.
*/

//Unsubscribe: stop listening for a given event
extenderWatcher.unsubscribe(eventExtenderUser);

Conclusion

By using the Event Operator and Event Processor, applications can easily emit and subscribe to events, maintain a decoupled architecture, and react dynamically to changes. Whether you’re working with predefined Zowe events or custom events, these tools offer a solid framework for managing and responding to events effectively.

Take advantage of the Event Operator and Event Processor to make your applications more flexible and responsive!

Learn More

If you would like to look more in-depth into this technology, feel free to check out the GitHub pull request responsible for the addition of this feature set to our codebase.

If you enjoyed this blog, read more Zowe blogs here. You can also ask a question in either the CLI GitHub discussions section or the Open Mainframe Project Slack Channel. Some relevant channels in this project are: #zowe-help, #zowe-cli, #zowe-explorer-vscode, and #zowe-apiml.

--

--