Posts tagged 'command bus'

Prooph command bus

published on November 07, 2017.

Prooph is a CQRS and Event Sourcing component for PHP, and as they state on their website:

Prooph components include everything to get you started with CQRS and Event Sourcing.

CQRS and Event Sourcing go hand in hand with Domain Driven Design, but can be used outside of DDD too. They are patterns and methodologies that are here to help us make complicated and complex software designs more manageable, and all around better. Or make them even more complicated and complex.

In any case, I believe DDD is the way to go forward, as it puts communication with business stakeholders front and center, and at the end of the day, communication is the key to the success of any software project.

A tiny drop of theory

CQRS stands for Command Query Responsibility Segregation.

It boils down to the idea that instead of having one model that does both writing to and reading from the storage layer, you instead split them in two separate models. Then one of those models is responsible only for writing, and the other model is responsible for reading. The write “side” handles the command part, and the read “side” handles the query part of these responsibilities.

If you’re interested in more theory around this, and you should be, read this article on CQRS by Martin Fowler and this Clarified CQRS article by Udi Dahan. The CQRS journey on MSDN and the CQRS pattern documentation helped me a great deal to get a better understanding of this topic.

As for Event Sourcing… We’ll get to that in another blog post, when we’ll talk about the Event Sourcing part of Prooph.

The command bus

Now, let’s get started with Prooph. The first component we’re going to look at is the Service Bus.

The service bus offers a messaging system between the application and the domain layer. It allows us to send, or dispatch, a message on this service bus, and then to have handlers on the other side of the service bus that we’ll use to, well, handle these messages.

Prooph’s service bus has three different kinds of buses:

  • the command bus — it dispatches one message, a command, to exactly one handler,
  • the event bus — it dispatches one message, an event, to zero or more event handlers,
  • and, the query bus — it dispatches one message, a query, to exactly one handler, but returns a React\Promise\Promise.

Today we’re going to look at — you’ve guessed it! — the command bus.

The command bus gives us the ability to send a command through the command bus itself, and dispatches that command to a command handler we specified. We send in a message, and on the otherside that same message comes out to the command handler.

It is worth mentioning that the command bus can be used as a standalone component, if you’re interested only in that part. You’re not required to do CQRS, Event Sourcing, and/or DDD, to be able to use the command bus. If all you want, or all you need, to do is send a command, and have that command handled on the other side, by all means, do just that.

The command bus can dispatch anything as a command: a primitive like a string or an integer, a Data Transfer Object (DTO) that represents our command, or a Prooph Message (an interface found in the prooph-common library).

We name these commands based on the action that we want to do: RegisterUser, FetchUrl, SendEmail.

To dispatch a command on the command bus, we do the following:

  • we create the command bus,
  • we create a command router that the command bus uses to route commands to command handlers,
  • we route a command to its command handler,
  • we attach the router to the command bus,
  • and finally, we dispatch the command on the command bus.

This sounds like an awful lot; a picture code example is worth a thousand words:

command-bus.php

<?php declare(strict_types=1);

require_once 'vendor/autoload.php';

use Prooph\ServiceBus\CommandBus;
use Prooph\ServiceBus\Plugin\Router\CommandRouter;

$commandBus = new CommandBus();

$commandRouter = new CommandRouter();

$commandRouter->route('A simple string')
    ->to(new \ProophExample\CommandHandler\Primitives());

$commandRouter->attachToMessageBus($commandBus);

$commandBus->dispatch('A simple string');

The Primitives command handler is an invokable that, for this example, only prints out the “primitive” command we dispatched to it for handling:

src/ProophExample/CommandHandler/Primitives.php

<?php declare(strict_types=1);

namespace ProophExample\CommandHandler;

class Primitives
{
    public function __invoke(string $primitiveCommand)
    {
        echo $primitiveCommand . PHP_EOL;
    }
}

In a real application it would do something a bit more meaningful.

If we run this command-bus.php example, we’d see this:

$ php command-bus.php
A simple string

If we’d tell the command bus to dispatch something else instead of 'A simple string':

<?php
$commandBus->dispatch('Some other string');

and we run the example script again, we’d get the following exception:

Prooph\ServiceBus\Exception\RuntimeException: CommandBus was not able to identify a CommandHandler for command Some other string

That’s because we told the $commandRouter to route the command 'A simple string', yet we dispatched 'Some other string'. Remember, every dispatched command must be handled by exactly one command handler, and in this case the command bus doesn’t know how to handle our command.

Going past primitives

Except for showing examples, I don’t think primitives as commands are really useful.

How I personally use the command bus, is by creating classes of commands, which are nothing else but DTOs:

src/ProophExample/Command/FetchUrl.php

<?php declare(strict_types=1);

namespace ProophExample\Command;

use ProophExample\Url;

class FetchUrl
{
    /**
    * @var Url
    */
    protected $url;

    public function __construct(string $url)
    {
        $this->url = Url::fromString($url);
    }

    public function url(): Url
    {
        return $this->url;
    }
}

A command is a good place to convert our primitives to value objects!

The accompanying command handler is:

src/ProophExample/CommandHandler/FetchUrl.php

<?php declare(strict_types=1);

namespace ProophExample\CommandHandler;

use ProophExample\Command;

class FetchUrl
{
    public function __invoke(Command\FetchUrl $command)
    {
        echo sprintf("Fetching url: %s", $command->url()) . PHP_EOL;
    }
}

Again, it doesn’t do much besides printing out the url that our command DTO transferred for us across the command bus.

The command bus follows the same principle: tell the command router what command to route to what command handler, create the command, and dispatch it on the command bus:

command-bus.php

<?php declare(strict_types=1);

require_once 'vendor/autoload.php';

use Prooph\ServiceBus\CommandBus;
use Prooph\ServiceBus\Plugin\Router\CommandRouter;

$commandBus = new CommandBus();

$commandRouter = new CommandRouter();

$commandRouter->route(ProophExample\Command\FetchUrl::class)
    ->to(new ProophExample\CommandHandler\FetchUrl());

$commandRouter->attachToMessageBus($commandBus);

$url = 'https://robertbasic.com/index.xml';
$command = new ProophExample\Command\FetchUrl($url);

$commandBus->dispatch($command);

Prooph Messages

As mentioned earlier, the commands can also be Prooph Messages. These are commands that implement the Prooph\Common\Messaging\Message interface.

Note that the prooph-common library not only provides us the interface(s) we should implement, but also some abstract classes and traits to do the “plumbing” for us.

Let’s see how what would this be like:

src/ProophExample/Command/RegisterUser.php

<?php declare(strict_types=1);

namespace ProophExample\Command;

use Prooph\Common\Messaging\Command;
use Prooph\Common\Messaging\PayloadConstructable;
use Prooph\Common\Messaging\PayloadTrait;
use ProophExample\Email;

class RegisterUser extends Command implements PayloadConstructable
{
    use PayloadTrait;

    public function email(): Email
    {
        return Email::fromString($this->payload['email']);
    }
}

The two interfaces, Message and HasMessageName, together with the Command abstract class, and the DomainMessage abstract class it extends, provide a type for our message (command in this case), a UUID, a date and time when the command was created, the payload of the command, and some meta data.

The PayloadConstructable interface and the PayloadTrait trait give us an implementation of a constructor that expects exactly one argument, an array, that holds the payload for our command.

To create this command, we do the following:

<?php
$payload = ['email' => 'john.doe@example.com'];
$command = new ProophExample\Command\RegisterUser($payload);

In the case of commands, I personally prefer a custom DTO, over a Message type.

A more real-world like example

The command-bus.php example from before doesn’t really show how would we use the command bus in a more real-life setting. When we want to dispatch a command somewhere in our application, we don’t want to deal with all the routing and stuff, we just want to send a command to the command bus to be handled by a command handler.

If we’re using Symfony, one option would be to create a custom factory for the command bus, where we create the command bus, the router for it, and route the commands to command handlers:

src/ProophExample/CommandBusFactory.php

<?php declare(strict_types=1);

namespace ProophExample;

use Prooph\ServiceBus\CommandBus;
use Prooph\ServiceBus\Plugin\Router\CommandRouter;
use Symfony\Component\DependencyInjection\ContainerInterface;

class CommandBusFactory
{
    public static function createCommandBus(ContainerInterface $container): CommandBus
    {
        $commandBus = new CommandBus();

        $router = new CommandRouter();

        $router->route(ProophExample\Command\FetchUrl::class)
            ->to($container->get(ProophExample\CommandHandler\FetchUrl::class));

        $router->attachToMessageBus($commandBus);

        return $commandBus;
    }
}

The relevant part in the service definition file would be:

app/config/services.xml

<service id="Prooph\ServiceBus\CommandBus" class="Prooph\ServiceBus\CommandBus">
    <factory service="ProophExample\CommandBusFactory" method="createCommandBus" />
    <argument type="service" id="service_container" />
</service>

Then somewhere in our application, for example in a controller, we can get the CommandBus from the container, and dispatch the command:

src/AppBundle/Controller/ExampleController.php

<?php
// namespace imports left out intentionally
class ExampleController extends Controller
{
    public function indexAction(Request $request)
    {
        $url = 'https://robertbasic.com/index.xml';
        $command = new ProophExample\Command\FetchUrl($url);

        $this->get(Prooph\ServiceBus\CommandBus::class)->dispatch($command);
    }
}

The Prooph ServiceBus also comes equipped with a psr/container compatible Prooph\ServiceBus\Container\CommandBusFactory factory. The proophesor-do application has an example how to configure and use it.

There’s also a Symfony bundle that provides integration of the ServiceBus with Symfony.

Some of the examples shown and discussed here are available in my prooph-examples repository.

Happy hackin’!

Using Tactician in a Zend Expressive application

published on July 13, 2016.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

I spent some time connecting the dots last week, so I decided to put together an example on how to get started with using Tactician in a Zend Expressive application. The example itself is not really useful, but it does show how to setup the dependencies and get started with these two libraries.

Zend Expressive is a PSR7 compatible microframework that provides interfaces for routing, DI containers, templating and error handling. It provides a couple out of the box, so you can either use those, or write your own implementations.

Tactician is a command bus library whose goal is to make using the command pattern easy to use in your applications. It allows to have an object that represents a command, pass it on to the command bus which will figure out which command handler should take care of that command.

Let’s dive in

To get up and running quickly with Zend Expressive we can create a skeleton application. It does some basic wiring for us, like setting up the routing and the DI container.

It also comes with a dummy ping action, at /api/ping, which just gives us the current unix timestamp. This example is going to expand on that and create a Ping command that will be handled by a Ping command handler. The command handler will get some additional dependencies from the container, just to make the example a bit more interesting.

Creating the skeleton application is really easy with Composer:

$ cd /var/www
$ composer create-project zendframework/zend-expressive-skeleton tactician-example

Bring in the Tactician and the tactician-container plugin as project dependencies. The tactician-container plugin allows us to lazy load command handlers from a container-interop compatible container:

$ composer require league/tactician
$ composer require league/tactician-container

Now that we have all our libraries in, let’s change how the container creates the Ping action. Before it was being just invoked by the container, but now we want to create it through a factory:

config/autoload/routes.global.php

diff --git a/config/autoload/routes.global.php b/config/autoload/routes.global.php
index 856f5ab..8335450 100644
--- a/config/autoload/routes.global.php
+++ b/config/autoload/routes.global.php
@@ -4,10 +4,10 @@ return [
     'dependencies' => [
         'invokables' => [
             Zend\Expressive\Router\RouterInterface::class => Zend\Expressive\Router\FastRouteRouter::class,
-            App\Action\PingAction::class => App\Action\PingAction::class,
         ],
         'factories' => [
             App\Action\HomePageAction::class => App\Action\HomePageFactory::class,
+            App\Action\PingAction::class => App\Action\PingFactory::class
         ],
     ],

This will allow us to pass in dependencies to the PingAction class.

The Ping action’s factory is simple:

src/App/Action/PingFactory.php

<?php

namespace App\Action;

use Interop\Container\ContainerInterface;

class PingFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $commandBus = $container->get('CommandBus');

        return new PingAction($commandBus);
    }
}

We are telling the container to get the service called CommandBus and pass it as an argument to the Ping action’s constructor.

Wiring in Tactician

We haven’t yet defined the CommandBus service, so let’s do that next by telling the service manager to create the CommandBus using the App\CommandBusFactory factory:

config/autoload/dependencies.global.php

diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php
index b2b08f5..460c045 100644
--- a/config/autoload/dependencies.global.php
+++ b/config/autoload/dependencies.global.php
@@ -19,6 +19,7 @@ return [
         'factories' => [
             Application::class => ApplicationFactory::class,
             Helper\UrlHelper::class => Helper\UrlHelperFactory::class,
+            'CommandBus' => App\CommandBusFactory::class
         ],
     ],
 ];

This factory sets up the Tactician’s command bus and is the main point of this example:

src/App/CommandBusFactory.php

<?php

namespace App;

use League\Tactician\CommandBus;
use League\Tactician\Handler\CommandHandlerMiddleware;
use League\Tactician\Container\ContainerLocator;
use League\Tactician\Handler\CommandNameExtractor\ClassNameExtractor;
use League\Tactician\Handler\MethodNameInflector\InvokeInflector;
use Interop\Container\ContainerInterface;

class CommandBusFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $inflector = new InvokeInflector();

        $commandsMapping = [];
        $locator = new ContainerLocator($container, $commandsMapping);

        $nameExtractor = new ClassNameExtractor();

        $commandHandlerMiddleware = new CommandHandlerMiddleware(
            $nameExtractor,
            $locator,
            $inflector
        );

        $commandBus = new CommandBus([
            $commandHandlerMiddleware
        ]);

        return $commandBus;
    }
}

Tactician uses a command handler middleware to handle commands. That middleware in turn uses a name extractor to get the command name out of a command, a locator to find the actual command handler and an inflector to figure out the method to call on the command handler to handle the command. Tactician’s middleware system is nicely described in the documentation.

The ClassNameExtractor will extract the command name from the class name.

The ContainerLocator will use our container-interop compatible container to find the command handler, which in this example is Zend ServiceManager.

The InvokeInflector dictates that the command handler needs to have an __invoke method which will get our Ping command as an argument and then it’s up to the Ping command handler to handle the command.

The $commandsMapping array that we are passing to the locator is going to be a map of commands and their handlers. We’ll populate that later on.

In the next step, let’s tell the PingAction’s constructor to accept the command bus:

src/App/Action/PingAction.php

diff --git a/src/App/Action/PingAction.php b/src/App/Action/PingAction.php
index ea2ae22..612fb32 100644
--- a/src/App/Action/PingAction.php
+++ b/src/App/Action/PingAction.php
@@ -5,9 +5,15 @@ namespace App\Action;
 use Zend\Diactoros\Response\JsonResponse;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
+use League\Tactician\CommandBus;

 class PingAction
 {
+    public function __construct(CommandBus $commandBus)
+    {
+        $this->commandBus = $commandBus;
+    }
+
     public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
     {
         return new JsonResponse(['ack' => time()]);

Cool, at this point we have everything set up to start sending and handling commands.

Commands and their handlers

The command we are going to create is a simple one:

src/App/Command/Ping.php

<?php

namespace App\Command;

class Ping
{
    private $commandTime;

    public function __construct()
    {
        $this->commandTime = time();
    }

    public function getCommandTime()
    {
        return $this->commandTime;
    }
}

It just sets the command time to the current unix timestamp.

Updating the PingAction to include the creation of our Ping command and passing it on to the command bus to be handled:

src/App/Action/PingAction.php

diff --git a/src/App/Action/PingAction.php b/src/App/Action/PingAction.php
index 612fb32..6cb9334 100644
--- a/src/App/Action/PingAction.php
+++ b/src/App/Action/PingAction.php
@@ -6,6 +6,7 @@ use Zend\Diactoros\Response\JsonResponse;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use League\Tactician\CommandBus;
+use App\Command\Ping as PingCommand;

 class PingAction
 {
@@ -16,6 +17,11 @@ class PingAction

     public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
     {
-        return new JsonResponse(['ack' => time()]);
+        $pingCommand = new PingCommand();
+        $time = $pingCommand->getCommandTime();
+
+        $this->commandBus->handle($pingCommand);
+
+        return new JsonResponse(['ack' => $time]);
     }
 }

Now is the time to let Tactician know about our command and command handler mapping, so it knows which handler handles which command:

src/App/CommandBusFactory.php

diff --git a/src/App/CommandBusFactory.php b/src/App/CommandBusFactory.php
index ba587f6..b79fbb1 100644
--- a/src/App/CommandBusFactory.php
+++ b/src/App/CommandBusFactory.php
@@ -9,13 +9,18 @@ use League\Tactician\Handler\CommandNameExtractor\ClassNameExtractor;
 use League\Tactician\Handler\MethodNameInflector\InvokeInflector;
 use Interop\Container\ContainerInterface;

+use App\Command\Ping as PingCommand;
+use App\CommandHandler\Ping as PingCommandHandler;
+
 class CommandBusFactory
 {
     public function __invoke(ContainerInterface $container)
     {
         $inflector = new InvokeInflector();

-        $commandsMapping = [];
+        $commandsMapping = [
+            PingCommand::class => PingCommandHandler::class
+        ];
         $locator = new ContainerLocator($container, $commandsMapping);

         $nameExtractor = new ClassNameExtractor();

We’re almost there. I promise.

The command handler is going to be created through a factory, so we can inject dependencies into it:

src/App/CommandHandler/PingFactory.php

<?php

namespace App\CommandHandler;

use Interop\Container\ContainerInterface;

class PingFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $logPath = '/tmp/ping-command.log';

        return new Ping($logPath);
    }
}

It doesn’t do much, it just passes a path to a log file. Of course, in real code, you’d probably pass in some dependency gotten from the container.

The command handler won’t do much either, it’s just going to log the the ping’s command time in the log file we passed in from the command handler factory:

src/App/CommandHandler/Ping.php

<?php

namespace App\CommandHandler;

use App\Command\Ping as PingCommand;

class Ping
{
    private $logPath;

    public function __construct($logPath)
    {
        $this->logPath = $logPath;
    }

    public function __invoke(PingCommand $pingCommand)
    {
        $commandTime = $pingCommand->getCommandTime();

        file_put_contents($this->logPath, $commandTime . PHP_EOL, FILE_APPEND);
    }
}

And finally let the service manager know how to create the Ping command handler:

config/autoload/dependencies.global.php

diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php
index 460c045..2c8e3ee 100644
--- a/config/autoload/dependencies.global.php
+++ b/config/autoload/dependencies.global.php
@@ -19,7 +19,8 @@ return [
         'factories' => [
             Application::class => ApplicationFactory::class,
             Helper\UrlHelper::class => Helper\UrlHelperFactory::class,
-            'CommandBus' => App\CommandBusFactory::class
+            'CommandBus' => App\CommandBusFactory::class,
+            App\CommandHandler\Ping::class => App\CommandHandler\PingFactory::class
         ],
     ],
 ];

Navigating to /api/ping should display the {“ack”:1468171544} response, and the log file at /tmp/ping-command.log should have the same timestamp logged.

That was a lot of code

I know, looks like an awful lot of code just to log a timestamp in a file somewhere. But the point is that even for more complicated commands and handlers the basic wiring stays the same — create the CommandBus factory, set up mapping of commands and handlers and the rest is pretty much the business logic of the application.

Happy hackin’!

P.S.: I’m trying out this new way of providing code samples by using diffs, so it’s easier to follow what changed where. Let me know how it looks, thanks!

Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2019
Get the feed