nass
nass

Reputation: 357

How to inject RabbitMqBundle producer into service?

I have a problem with injecting RabbitMq producer from RabbitMqBundle into my service.

Service:

namespace App\Service;

use Carbon\Carbon;
use Doctrine\ORM\EntityManagerInterface;
use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface;

class RatingPositionRecalculateService
{

    protected $entityManager;

    protected $positionProducer;

    public function __construct(EntityManagerInterface $entityManager, ProducerInterface $producer)
    {
        $this->entityManager = $entityManager;
        $this->positionProducer = $producer;
    }

    public function recalculate(Carbon $day)
    {
        // do stuff
    }

}

old_sound_rabbit_mq.yml:

old_sound_rabbit_mq:
    connections:
        default:
            url: ''

    producers:
        rating_position:
            connection:       default
            exchange_options: { name: 'rating_position', type: direct }

    consumers:
        rating_position:
            connection:       default
            exchange_options: {name: 'rating_position', type: direct}
            queue_options:    {name: 'rating_position'}
            callback:         rating_position_service

and I get:

Cannot autowire service "App\Service\RatingPositionRecalculateService": argument "$producer" of method "__construct()" references interface "OldSound\RabbitMqBundle\RabbitMq\ProducerInterface" but no such service exists. You should maybe alias this interface to the existing "old_sound_rabbit_mq.rating_position_producer" service. Did you create a class that implements this interface?

I've tried wiring using services.yml:

rating_position_recalculate_service:
        class: App\Service\RatingPositionRecalculateService
        autowire: false
        arguments:
            $entityManager: '@doctrine.orm.entity_manager'
            $producer: '@old_sound_rabbit_mq.rating_position_producer'

but I still get the same exception.

Upvotes: 5

Views: 4517

Answers (2)

Nek
Nek

Reputation: 3123

I don't think your problem is related to the bundle. Your service definition looks ok. They wrote it in the documentation:

Here we configure the connection service and the message endpoints that our application will have. In this example your service container will contain the service old_sound_rabbit_mq.upload_picture_producer and old_sound_rabbit_mq.upload_picture_consumer. The later expects that there's a service called upload_picture_service.

Which means you should have a service old_sound_rabbit_mq.rating_position_producer. You can verify it by using the command bin/console debug:cont --show-private | grep old_sound_rabbit_mq.

But the problem is probably somewhere else.

Here is what I guess:

  • You have a configuration file that registers all your classes as service
  • You have another config file for your RatingPositionRecalculateService

If it's true, then the error is due to the duplicated registration of your service. While registering all the services, Symfony DIC tries to register your RatingPositionRecalculateService but can't link it to the producer (because the producer is not registered in the same file). You may have a look at another problem which has a similar issue: External service configuration in Symfony 4

Upvotes: 1

fxbt
fxbt

Reputation: 2596

If you only have one producer, you can define an alias like this in your services.yaml:

OldSound\RabbitMqBundle\RabbitMq\ProducerInterface: '@old_sound_rabbit_mq.rating_position_producer'

But i suggest you to create an empty class for your producer:

// src/Producer/RatingPositionProducer.php

<?php

namespace App\Producer;

class RatingPositionProducer extends \OldSound\RabbitMqBundle\RabbitMq\Producer
{
}

Then, in your old_sound_rabbit_mq.yml file:

old_sound_rabbit_mq:
    ...
    producers:
        rating_position:
           class: App\Producer\RatingPositionProducer
           ...

In your services.yaml file:

App\Producer\RatingPositionProducer: '@old_sound_rabbit_mq.rating_position_producer'

And finally, in your RatingPositionRecalculateService class

// src/Service/RatingPositionRecalculateService.php

namespace App\Service;

use Carbon\Carbon;
use Doctrine\ORM\EntityManagerInterface;
use App\Producer\RatingPositionProducer;

class RatingPositionRecalculateService
{
    ...

    public function __construct(EntityManagerInterface $entityManager, RatingPositionProducer $producer)
    {
        ...
    }

Upvotes: 11

Related Questions