All pages
Powered by GitBook
1 of 4

Loading...

Loading...

Loading...

Loading...

Message Endpoints/Handlers

Message Endpoint PHP

Message Endpoints/Handlers are consumers and producers of messages. Consumer are not necessary asynchronous, as you may build synchronous flow, compound of multiple endpoints. You will not have to implement them directly, as you should not even have to build messages and invoke or receive message directly from the Message channel. Instead you will be able to focus on your specific domain model with with an implementation based on plain PHP objects. By providing declarative configuration, you can "connect” your domain-specific code to the messaging infrastructure provided by Ecotone.

All Message Handlers follows simple low level interface

interface MessageHandler
{
    /**
     * Handles given message
     */
    public function handle(Message $message): void;
}

Command Handlers, Event Handlers, Query Handlers are also Endpoints.

Internal Message Handler

Service Activator PHP

The Internal Handler connecting any service available in Depedency Container to an input channel so that it may play the role of a Endpoint. If the service produces output, it may also be connected to an output channel.

How to register

class Shop
{
    #[InternalHandler("buyProduct")] 
    public function buyProduct(int $productId) : void
    {
        echo "Product with id {$productId} was bought";
    }
}

Possible options

  • endpointId - Endpoint identifier

  • inputChannnelName - Required option, defines to which channel endpoint should be connected

  • outputChannelName - Channel where result of method invocation will be

requiredInterceptorNames - List of interceptor names, which should intercept the endpoint

Splitter

Splitter PHP

The Splitter is endpoint where message can be splitted in several parts and be sent to be processed indepedently.

class Shop
{
    #[Splitter(inputChannelName="buyProduct", outputChannelName="buySingleProduct")]
    public function sendMultipleOrders(array $products) : array
    {
        return $products;
    }

    #[ServiceActivator("buySingleProduct")] 
    public function buyProduct(string $productName) : void
    {
        echo "Product {$productName} was bought";
    }
}

Possible options

  • endpointId - Endpoint identifier

  • inputChannnelName - Required option, defines to which channel endpoint should be connected

  • outputChannelName - Channel where result of method invocation will be

  • requiredInterceptorNames - List of names, which should intercept the endpoint

interceptor

Message Router

Message Router PHP

Routers consume messages from a message channel and forward each consumed message to one or more different message channels depending on a defined conditions.

Router must return name of the channel, where the message should be routed too. It can be array of channel names, if there are more.

class OrderRouter
{
    #[Router("make.order")] 
    public function orderSpecificType(string $orderType) : string
    {
        return $orderType === 'coffee' ? "orderInCoffeeShop" : "orderInGeneralShop";
    }
}

Possible options

  • endpointId - Endpoint identifier

  • inputChannnelName - Required option, defines to which channel endpoint should be connected

  • isResolutionRequired - If true, will throw exception if there was no channel name returned

Routing to multiple Message Channels

What can be Router used for?

Router is powerful concept that is backing up Query/Command and Event Bus implementations. Together with , you may roll up your own Bus implementation or build workflow pipelines.

Own Bus implementation

Message Gateway
class OrderRouter
{
    #[Router("order.bought")] 
    public function distribute(string $order) : array
    {
        // list of Channel names to distribute Message too
        return [
            'audit.store',
            'notification.send',
            'order.close'
        ];
    }
}
interface QueryGateway
{
    #[MessageGateway("query.router")]
    public function query(string $queryEndpoint): string;
}

final class QueryService
{
    #[Router("query.router")]
    public function getQuery(string $shopName): string
    {
        return sprintf("query-%s-shop", $shopName);
    }
}

final class ShopQueryHandler
{
    #[QueryHandler("query-coffee-shop")]
    public function queryOne(): string
    {
        return "coffee";
    }

//  We are routing directly to given channel name, so we use lower level abstraction ServiceActivator
//  The benefit of it is, that endpoint is actually hidden and can not be called directly from QueryBus.
    #[ServiceActivator("query-milk-shop")]
    public function queryTwo(): string
    {
        return "milk";
    }
}