1

I am new to Symfony framework and am trying to set up a project with Messenger (https://symfony.com/doc/current/messenger.html). My understanding is after setting up the handler class with “implements MessageHandlerInterface” the handler should be available for use but it does not seem to be working for me. I have tried several different things including setting up a new project from scratch. I am using Symfony 5.0.4.

I set up the project like this:

symfony new --full testMessenger
composer require messenger
php bin/console make:controller

Then I made a new messenger and handler and called it from the controller. Doing that I get the exception: “No handler for message "App\Message\Message".

php bin/console debug:messenger

Output:

Messenger 
========= 

messenger.bus.default 
--------------------- 

The following messages can be dispatched: 

-----------------------------------------------------  
 Symfony\Component\Mailer\Messenger\SendEmailMessage   
     handled by mailer.messenger.message_handler       
 Symfony\Component\Notifier\Message\ChatMessage        
     handled by chatter.messenger.chat_handler         
 Symfony\Component\Notifier\Message\SmsMessage         
     handled by texter.messenger.sms_handler           
-----------------------------------------------------  

My code is basically the same as the samples in the message handler documentation, but I will add it here.

// src/Message.php
<?php

namespace App\Message;

class Message
{
    private $content;

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

    public function getContent(): string
    {
        return $this->content;
    }
}


// src/MessageHandler.php
<?php

namespace App\MessageHandler;

use App\Message\Message;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class SmsNotificationHandler implements MessageHandlerInterface
{
    public function __invoke(Message $message)
    {
        // ... do some work - like sending an SMS message!
    }
}


// src/Controller/MessageController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use App\Message\Message;

class MessageController extends AbstractController
{
    /**
     * @Route("/message", name="message")
     */
    public function index()
    {
        $this->dispatchMessage(new Message('Look! I created a message!'));

        return $this->render('message/index.html.twig', [
            'controller_name' => 'MessageController',
        ]);
    }
}




//config/packages/messenger.yaml

    framework:

    messenger:
        # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
        # failure_transport: failed

        transports:
            # https://symfony.com/doc/current/messenger.html#transport-configuration
            # async: '%env(MESSENGER_TRANSPORT_DSN)%'
            # failed: 'doctrine://default?queue_name=failed'
            # sync: 'sync://'

        routing:
            # Route your messages to the transports
            # 'App\Message\YourMessage': async
user1404617
  • 585
  • 1
  • 5
  • 20
  • 1
    Could you add Messenger config also – qdequippe Feb 03 '20 at 11:44
  • @qdequippe I add the content of config/packages/messenger.yaml. – user1404617 Feb 03 '20 at 22:20
  • 1
    Thanks. I see "// src/MessageHandler.php" but your class name is "SmsNotificationHandler" is there a typo? – qdequippe Feb 04 '20 at 10:58
  • @qdequippe That was a typo. Thanks for pointing it out. That did not seem to change anything but I did figure out what it was. The name spaces have to match the directory structure exactly. I had put the classes in the src folder while keeping the name space from the example. That is interesting because that should not be the case in the original project where I was having these issues. I will review that carefully for name space issues. – user1404617 Feb 04 '20 at 16:47

1 Answers1

2

I've struggled a little with similar case, so I hope this will help someone:

So I had autowiring on and multiple buses defined like this:

final class QueryBus implements QueryBusInterface
{
    use HandleTrait {
        HandleTrait::handle as messengerHandle;
    }

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

    public function handle(object $query): mixed
    {
        return $this->messengerHandle($query);
    }
}

final class CommandBus implements CommandBusInterface
{
    use HandleTrait;

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

    public function dispatch(object $command)
    {
        return $this->handle($command);
    }
}
// messenger.yaml
framework:
    messenger:

        default_bus: command_bus
        buses:
            command_bus: ~
            query_bus: ~

And I got the same error for when dispatching a query "No handler for message..."

Eventually what helped was:

  1. Turn off autowiring in Bus implementation directories (by excluding paths in services.yaml.
    App\:
        resource: '../src/'
        exclude:
            - '../src/Bus/'

  1. Manually define the services:
// services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\src\Bus\CommandBus:
        arguments:
            - '@command_bus'

    App\src\Bus\QueryBus:
        arguments:
            - '@query_bus'

So actually it seems it was autowiring issue - failing to autowire 2 implementations of same Interface (the MessageBusInterface). The actual error of missing service was hiding under the messenger component.

Julius
  • 31
  • 3