Hello,
Since the release of doctrine-bundle:2.2.0, we are facing a strange issue with our EntityListeners not called only when symfony run under prod env. Note, It works normally on dev and test env.
To give you more context, our EntityListener is registered on a MappedSuperClasss and not directly on the final Entity class. But we never had an issue with this before the 2.2.0 release.
Here is how we register our EntityListener (the service is registered inside a vendor managed by us):
SAM\DealFlowBundle\EventListener\DealFlowListener:
arguments:
- '%sam_entities%'
tags:
- { name: doctrine.orm.entity_listener, event: prePersist, entity: SAM\DealFlowBundle\Entity\DealFlow, method: prePersist, lazy: true, priority: 100 }
Here is the DealFlowListener:
<?php
namespace SAM\DealFlowBundle\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use SAM\CommonBundle\Utils\LoggerUtils;
use SAM\DealFlowBundle\Entity\DealFlow;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* class DealFlowListener.
*/
class DealFlowListener
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var array
*/
protected $entities;
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var LoggerInterface
*/
private $logger;
/**
* DealFlowListener constructor.
*
* @param array $entities
* @param TokenStorageInterface $tokenStorage
*/
public function __construct($entities, TokenStorageInterface $tokenStorage, LoggerInterface $logger)
{
$this->tokenStorage = $tokenStorage;
$this->entities = $entities;
$this->logger = $logger;
}
/**
* @param DealFlow $deal
* @param LifecycleEventArgs $args
*
* @throws \Exception
*/
public function prePersist(DealFlow $deal, LifecycleEventArgs $args)
{
$this->logger->info('[DealFlowListener] prePersist called');
// Some code here removed from this snippet to keep it simple
}
The mappedsuperclass, DealFlow:
<?php
namespace SAM\DealFlowBundle\Entity;
use ...
/**
* @ORM\Table(
* name="deal_flow",
* indexes={@ORM\Index(name="project_name_index", columns={"project_name"}, flags={"fulltext"})},
* uniqueConstraints={@ORM\UniqueConstraint(name="legal_entity_deal_flow", columns={"legal_entity_id", "legal_entity_deal_flow_id"})}
* )
* @ORM\MappedSuperclass()
* @ORM\HasLifecycleCallbacks()
*
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
*/
class DealFlow
{
// ...
}
And the DealFlow final entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use SAM\DealFlowBundle\Entity\DealFlow as BaseDealFlow;
/**
* @ORM\Entity
*/
class DealFlow extends BaseDealFlow
{
}
Also, when i run bin/console --env=prod debug:container DealFlowListener on production, the service appears and it's registered into the container :

For now we have fix our composer.json to doctrine-bundle 2.1.2 and it works.
Our environment :
Our composer.json:
{
"name": "*******",
"description": "",
"license": "proprietary",
"type": "project",
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"require": {
"php": ">=7.2",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-ldap": "*",
"ext-pdo": "*",
"ext-soap": "*",
"ext-zip": "*",
"ext-zlib": "*",
"algolia/search-bundle": "^4.1",
"anyx/login-gate-bundle": "^2.0",
"beberlei/doctrineextensions": "^1.2",
"cocur/slugify": "^4.0",
"composer/package-versions-deprecated": "^1.8",
"damienharper/doctrine-audit-bundle": "^3.4",
"debril/rss-atom-bundle": "^5.0",
"doctrine/common": "^2.11",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-fixtures-bundle": "^3.3",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"eightpoints/guzzle-bundle": "^8.2",
"endroid/qr-code": "^3.9",
"endroid/qr-code-bundle": "^3.4",
"enqueue/amqp-lib": "^0.9.12",
"enqueue/enqueue-bundle": "^0.10.3",
"evence/soft-deleteable-extension-bundle": "^2.0.0",
"fresh/doctrine-enum-bundle": "^6.6",
"friendsofsymfony/ckeditor-bundle": "^2.2",
"friendsofsymfony/jsrouting-bundle": "^2.6",
"friendsofsymfony/user-bundle": "^2.1",
"fzaninotto/faker": "^1.9",
"garethp/php-ews": "^0.9.9",
"guzzlehttp/guzzle": "~6.0",
"incenteev/composer-parameter-handler": "^2.1",
"jeroendesloovere/vcard": "^1.7",
"knplabs/knp-gaufrette-bundle": "^0.7.1",
"knplabs/knp-paginator-bundle": "^5.3",
"knplabs/knp-snappy-bundle": "^1.7",
"knplabs/knp-time-bundle": "^1.13",
"kunalvarma05/dropbox-php-sdk": "^0.2.1",
"lexxpavlov/settingsbundle": "^1.5.1",
"liip/imagine-bundle": "^2.3",
"loilo/fuse": "^3.6",
"monolog/monolog": "^1.3",
"mysam/environment-symfony-tools": "^2.0",
"mysam/sortable-behavior-bundle": "^1.5",
"nyholm/effective-interest-rate": "^1.0",
"ocramius/proxy-manager": "2.1.*",
"phpoffice/phpspreadsheet": "^1.15",
"portphp/spreadsheet": "^1.0",
"scheb/two-factor-bundle": "^4.18",
"sensio/framework-extra-bundle": "^5.6",
"sentry/sentry-symfony": "^3.5",
"sonata-project/admin-bundle": "^3.63",
"sonata-project/doctrine-extensions": "^1.9",
"sonata-project/doctrine-orm-admin-bundle": "^3.22",
"sonata-project/exporter": "^2.4",
"sonata-project/form-extensions": "^1.6",
"sonata-project/twig-extensions": "^1.4",
"stechstudio/backoff": "^1.1",
"stof/doctrine-extensions-bundle": "^1.5",
"suncat/mobile-detect-bundle": "dev-master",
"symfony/asset": "4.4.*",
"symfony/cache": "4.4.*",
"symfony/console": "4.4.*",
"symfony/dotenv": "4.4.*",
"symfony/flex": "^1.3.1",
"symfony/framework-bundle": "4.4.*",
"symfony/ldap": "4.4.*",
"symfony/lock": "4.4.*",
"symfony/mailer": "4.4.*",
"symfony/monolog-bundle": "^3.5",
"symfony/polyfill-apcu": "^1.18",
"symfony/property-info": "4.4.*",
"symfony/proxy-manager-bridge": "4.4.*",
"symfony/serializer": "4.4.*",
"symfony/translation": "4.4.*",
"symfony/twig-bundle": "4.4.*",
"twig/extensions": "^1.5",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12",
"vich/uploader-bundle": "^1.15"
},
"require-dev": {
"dama/doctrine-test-bundle": "^6.3",
"doctrine/data-fixtures": "^1.4",
"escapestudios/symfony2-coding-standard": "^3.11",
"hautelook/alice-bundle": "^2.7",
"johnkary/phpunit-speedtrap": "^3.2",
"liuggio/fastest": "^1.7",
"phpunit/phpunit": "8.5.8",
"sempro/phpunit-pretty-print": "^1.2",
"symfony/browser-kit": "^4.4",
"symfony/css-selector": "4.4.*",
"symfony/debug-bundle": "^4.4",
"symfony/maker-bundle": "^1.21",
"symfony/phpunit-bridge": "^5.1",
"symfony/stopwatch": "^4.4",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4",
"symplify/easy-coding-standard": "^8.3",
"theofidry/alice-data-fixtures": "^1.2"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/Software-For-Asset-Management/MobileDetectBundle"
}
],
"scripts": {
"php-cs-fixer": "php vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix vendor/sam/ --rules=@Symfony",
"auto-scripts": {
"cache:clear": "symfony-cmd",
"ckeditor:install --clear=drop": "symfony-cmd",
"assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd",
"sam:bin:install": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"replace": {
"paragonie/random_compat": "2.*",
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php71": "*",
"symfony/polyfill-php70": "*",
"symfony/polyfill-php56": "*"
},
"conflict": {
"symfony/symfony": "*"
},
"config": {
"preferred-install": {
"*": "dist"
},
"sort-packages": true,
"platform": {
"php": "7.2.22"
}
},
"extra": {
"symfony": {
"allow-contrib": true,
"require": "4.4.*"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
This might very well be relevant https://github.com/doctrine/DoctrineBundle/pull/1196. Can you check if reverting those changes fixes your issue?
Hi @ostrolucky , i confirm, by reverting the two commits it works.
Here is the repository with the revert commits: https://github.com/Software-For-Asset-Management/DoctrineBundle/tree/master
Reproducer would be more useful. I'm unable to reproduce the issue. Tried with 2.2.0, under prod, with prePersist, with @ORM\MappedSuperclass, without @ORM\EntityListeners. Listener is triggered every time.
Have the same issue with 2.2.0, with postPersist event.
For reproduce just needed run cache warm up:
bin/console cache:warmup --env=prod --no-debug

Indeed, I've reproduced this now
@zubov-ruslan how exactly did you produce this diff in the screenshot? So in one default_metadata.php file the entitylisteners are present and in the other one not?
So far I can reproduce the missing case. But I cannot get it to show entitylisteners with 2.2.0 on my project
@dmaicher it happens when you run bin/console cache:warmup --env=prod --no-debug for the second time
We decided to rollback the change which caused this issue. We released 2.2.1 which should fix your issue.
@dmaicher Did you be able to reproduce?
@zubov-ruslan I can't reproduce even after run cache warmup multiple times. Do you do something between two calls of cache warmup? What is your metadata_cache_driver configuration? Do you use one or several entity managers?
Crucial part for reproducing is not defining @ORM\EntityListeners, listener needs to be solely defined via service definition only.
@ostrolucky I've changed the listener definition from annotations to services, but everything still works. Just difference is a new service listener appears in the container.
bug is only in prod mode, with warmed up cache, since that's where feature works
I've reproduced this. When entity listeners declared using services config they are added to metadata using event manager in AttachEntityListenersListener. When we warming up the php array cache we creating a clear ClassMetadataFactory with no event listeners. Using ClassMetadataFactory from container should fix this, I'll try to create a fix.
Since AttachEntityListenersListener attach listener only once the best solution I see is to set the highest priority to DoctrineMetadataCacheWarmer.
@PierrickMartos @zubov-ruslan Could you please check this solution, please checkout to 2.2.0 and change this line ->addTag('kernel.cache_warmer'); to ->addTag('kernel.cache_warmer', ['priority' => 1000]);?
I would really suggest to give us a feedback and try the suggested changes if you don't want us to break your application again in next release.
I try to find a moment to reproduce it in coming days
Hi @ossinkine i've made some tests, i confirm that it doesnt work when changing ->addTag('kernel.cache_warmer'); to ->addTag('kernel.cache_warmer', ['priority' => 1000]);