diff --git a/doc/routing.md b/doc/routing.md
index ef8c008..110f5a0 100644
--- a/doc/routing.md
+++ b/doc/routing.md
@@ -61,6 +61,10 @@ The bundle will try to detect the message itself
by analyzing the methods of the handler and creating instances of the message objects.
But don't worry about performance because this will happen on compiling.
+> **Important:** Automatic message detection can only detect handlers where either
+> the message implements `Prooph\Common\Messaging\HasMessageName` or the
+> name of the method is `__invoke`. In both cases the object must be a non abstract class.
+
> **Hint:** If you rely on automatic message detection and your handler handles multiple messages of the same message bus,
> you need to tag the handler just once.
diff --git a/src/DependencyInjection/Compiler/RoutePass.php b/src/DependencyInjection/Compiler/RoutePass.php
index 2143fe9..c21528f 100644
--- a/src/DependencyInjection/Compiler/RoutePass.php
+++ b/src/DependencyInjection/Compiler/RoutePass.php
@@ -18,6 +18,9 @@ class RoutePass implements CompilerPassInterface
{
private static function detectMessageName(ReflectionClass $messageReflection): ?string
{
+ if (! $messageReflection->implementsInterface(HasMessageName::class)) {
+ return $messageReflection->getName();
+ }
$instance = $messageReflection->newInstanceWithoutConstructor(); /* @var $instance HasMessageName */
if ($messageReflection->hasMethod('init')) {
$init = $messageReflection->getMethod('init');
@@ -111,7 +114,8 @@ private function recognizeMessageNames(
function (ReflectionMethod $method) {
return ($method->getNumberOfRequiredParameters() === 1 || $method->getNumberOfRequiredParameters() === 2)
&& $method->getParameters()[0]->getClass()
- && $method->getParameters()[0]->getClass()->implementsInterface(HasMessageName::class)
+ && ($method->getParameters()[0]->getClass()->implementsInterface(HasMessageName::class)
+ || $method->getName() === '__invoke')
&& ! ($method->getParameters()[0]->getClass()->isInterface()
|| $method->getParameters()[0]->getClass()->isAbstract()
|| $method->getParameters()[0]->getClass()->isTrait());
diff --git a/test/DependencyInjection/AbstractServiceBusExtensionTestCase.php b/test/DependencyInjection/AbstractServiceBusExtensionTestCase.php
index 7278969..7642ca4 100644
--- a/test/DependencyInjection/AbstractServiceBusExtensionTestCase.php
+++ b/test/DependencyInjection/AbstractServiceBusExtensionTestCase.php
@@ -31,8 +31,10 @@
use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\AcmeRegisterUserCommand;
use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\AcmeRegisterUserHandler;
use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\AcmeUserWasRegisteredEvent;
+use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\CommandHandlerForPopoCommand;
use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\CommandWithPrivateConstructor;
use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\MockPlugin;
+use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\PopoCommand;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
@@ -357,6 +359,25 @@ public function it_adds_command_bus_routes_based_on_tags_with_automatic_message_
$commandBus->dispatch(CommandWithPrivateConstructor::create());
}
+ /**
+ * @test
+ */
+ public function it_supports_automatic_message_detection_with_popo_messages_and_invokable_handlers()
+ {
+ $container = $this->loadContainer('command_bus_with_tags', new PluginsPass(), new RoutePass());
+
+ /* @var $commandBus CommandBus */
+ $commandBus = $container->get('prooph_service_bus.main_command_bus');
+
+ /** @var CommandHandlerForPopoCommand $mockHandler */
+ $mockHandler = $container->get(CommandHandlerForPopoCommand::class);
+ $command = new PopoCommand();
+
+ $commandBus->dispatch($command);
+
+ self::assertSame($command, $mockHandler->lastCommand);
+ }
+
/**
* @test
*/
diff --git a/test/DependencyInjection/Fixture/Model/CommandHandlerForPopoCommand.php b/test/DependencyInjection/Fixture/Model/CommandHandlerForPopoCommand.php
new file mode 100644
index 0000000..c1a972e
--- /dev/null
+++ b/test/DependencyInjection/Fixture/Model/CommandHandlerForPopoCommand.php
@@ -0,0 +1,25 @@
+lastCommand = $command;
+ }
+
+ /**
+ * Do not take notice of this method.
+ * It is necessary to run the tests against prooph/service-bus:6.0.0
+ * @see https://github.com/prooph/service-bus/pull/159
+ */
+ public function handle(): void
+ {
+ }
+}
diff --git a/test/DependencyInjection/Fixture/Model/PopoCommand.php b/test/DependencyInjection/Fixture/Model/PopoCommand.php
new file mode 100644
index 0000000..52522c3
--- /dev/null
+++ b/test/DependencyInjection/Fixture/Model/PopoCommand.php
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/test/DependencyInjection/Fixture/config/yml/command_bus_with_tags.yml b/test/DependencyInjection/Fixture/config/yml/command_bus_with_tags.yml
index 6b6d95f..904c0d9 100644
--- a/test/DependencyInjection/Fixture/config/yml/command_bus_with_tags.yml
+++ b/test/DependencyInjection/Fixture/config/yml/command_bus_with_tags.yml
@@ -19,3 +19,8 @@ services:
ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\CommandHandlerForCommandWithPrivateConstructor:
tags:
- { name: 'prooph_service_bus.main_command_bus.route_target', message_detection: true }
+
+ ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\CommandHandlerForPopoCommand:
+ public: true
+ tags:
+ - { name: 'prooph_service_bus.main_command_bus.route_target', message_detection: true }