├── .gitignore ├── ActiveMq ├── Base.php ├── Connection.php ├── Consumer.php ├── ConsumerInterface.php ├── Message.php └── Publisher.php ├── Command ├── ConsumerCommand.php └── ProducerCommand.php ├── DependencyInjection ├── Configuration.php └── OverblogActiveMqExtension.php ├── Exception └── ActiveMqException.php ├── LICENSE ├── OverblogActiveMqBundle.php ├── README.md ├── Resources └── config │ └── services.yml └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Bootstrap 2 | app/bootstrap* 3 | 4 | # Symfony directories 5 | vendor/* 6 | */logs/* 7 | */cache/* 8 | web/uploads/* 9 | web/bundles/* 10 | 11 | # Configuration files 12 | app/config/parameters.ini 13 | 14 | # composer 15 | composer.lock 16 | -------------------------------------------------------------------------------- /ActiveMq/Base.php: -------------------------------------------------------------------------------- 1 | connection = $connection; 34 | $this->options = new ParameterBag($options); 35 | } 36 | 37 | /** 38 | * Return destination string 39 | * @param string $routing_key 40 | * @param boolean $concat_key 41 | * @return string 42 | * @throws ActiveMqException 43 | */ 44 | public function getDestination($routing_key = null, $concat_key = false) 45 | { 46 | if(in_array($this->options->get('type'), array('queue', 'topic'))) 47 | { 48 | $destination = sprintf('/%s/%s', 49 | $this->options->get('type'), 50 | $this->options->get('name') 51 | ); 52 | 53 | if(true === $concat_key && !empty($routing_key)) 54 | { 55 | $destination = preg_replace('#\\' . $this->options->get('separator') . '>|\*$#', '', $destination); 56 | 57 | $destination .= $this->options->get('separator') . $routing_key; 58 | } 59 | 60 | return $destination; 61 | } 62 | else 63 | { 64 | throw new ActiveMqException('Wrong destination type'); 65 | } 66 | } 67 | 68 | /** 69 | * Purge given destination 70 | * @param string $routing_key 71 | * @param boolean $concat_key 72 | */ 73 | public function purge($routing_key = null, $concat_key = false) 74 | { 75 | $this->connection->purge($this->getDestination($routing_key, $concat_key)); 76 | } 77 | } -------------------------------------------------------------------------------- /ActiveMq/Connection.php: -------------------------------------------------------------------------------- 1 | options = $options; 34 | } 35 | 36 | /** 37 | * Return and instanciate connection if needed 38 | * @return StompConnection 39 | */ 40 | public function getConnection() 41 | { 42 | if(is_null($this->connection)) 43 | { 44 | $this->connection = new StompConnection( 45 | $this->getConnectionFactory() 46 | ); 47 | 48 | $this->connection->connect( 49 | $this->options['user'], 50 | $this->options['password'], 51 | $this->options['version'] 52 | ); 53 | } 54 | 55 | return $this->connection; 56 | } 57 | 58 | protected function getConnectionFactory() 59 | { 60 | if(count($this->options['servers']) == 1) 61 | { 62 | // Single connection 63 | return new Simple($this->getBrokerUri( 64 | current($this->options['servers']) 65 | )); 66 | } 67 | else 68 | { 69 | // Failover connection 70 | $servers = array(); 71 | 72 | foreach($this->options['servers'] as $server) 73 | { 74 | $servers[] = $this->getBrokerUri($server); 75 | } 76 | 77 | return new Failover($servers, $this->options['randomize_failover']); 78 | } 79 | } 80 | 81 | /** 82 | * Create broker URI 83 | * http://activemq.apache.org/failover-transport-reference.html 84 | * 85 | * @param array $params 86 | * @return string 87 | */ 88 | protected function getBrokerUri(array $params) 89 | { 90 | $options = array(); 91 | 92 | // Base URI 93 | $uri = 'tcp://' . $params['uri']; 94 | 95 | if(true === $params['useAsyncSend']) 96 | { 97 | $options['useAsyncSend'] = 'true'; 98 | } 99 | 100 | if(!is_null($params['startupMaxReconnectAttempts'])) 101 | { 102 | $options['startupMaxReconnectAttempts'] = 103 | $params['startupMaxReconnectAttempts']; 104 | } 105 | 106 | if(!is_null($params['maxReconnectAttempts'])) 107 | { 108 | $options['maxReconnectAttempts'] = 109 | $params['maxReconnectAttempts']; 110 | } 111 | 112 | if(count($options) > 0) 113 | { 114 | $uri.= '?' . http_build_query($options); 115 | } 116 | 117 | return $uri; 118 | } 119 | 120 | /** 121 | * Purge queue or topic 122 | * @param string $queue 123 | */ 124 | public function purge($queue) 125 | { 126 | $stomp = $this->getConnection(); 127 | $header = array('id' => sprintf('purge:%s', $queue)); 128 | 129 | // No need to wait more than 1s if there is no messages in queue 130 | $stomp->setReadTimeout(1, 0); 131 | 132 | $stomp->subscribe($queue, $header); 133 | 134 | while($stomp->hasFrameToRead()) 135 | { 136 | $stomp->ack($stomp->readFrame()); 137 | } 138 | 139 | $stomp->unsubscribe($queue, $header); 140 | 141 | // Disconnect & delete connection 142 | $this->close(); 143 | } 144 | 145 | /** 146 | * Close the connection 147 | */ 148 | public function close() 149 | { 150 | if(!is_null($this->connection)) 151 | { 152 | $this->connection->disconnect(); 153 | $this->connection = null; 154 | } 155 | } 156 | 157 | public function __destruct() 158 | { 159 | $this->close(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /ActiveMq/Consumer.php: -------------------------------------------------------------------------------- 1 | handler = $handler; 32 | 33 | parent::__construct($connection, $options); 34 | } 35 | 36 | /** 37 | * Set routing key 38 | * @param string $routing_key 39 | */ 40 | public function setRoutingKey($routing_key) 41 | { 42 | $this->routing_key = $routing_key; 43 | } 44 | 45 | /** 46 | * Consume messages 47 | * @param int $msgAmount 48 | */ 49 | public function consume($msgAmount) 50 | { 51 | $stomp = $this->connection->getConnection(); 52 | $id = $this->getHeaders()['id']; 53 | 54 | $stomp->subscribe($this->getDestination($this->routing_key), $this->getHeaders()); 55 | 56 | // Infinite loop 57 | if($msgAmount <= 0) $msgAmount = -1; 58 | 59 | while($msgAmount != 0) 60 | { 61 | if($stomp->hasFrameToRead()) 62 | { 63 | // Inject frame into ActimeMQ message 64 | $frame = $stomp->readFrame(); 65 | $msg = new Message($frame->body, $frame->headers); 66 | 67 | if (false !== call_user_func(array($this->handler, 'execute'), $msg)) 68 | { 69 | $stomp->ack($frame); 70 | } 71 | 72 | $msgAmount --; 73 | } 74 | } 75 | 76 | $stomp->unsubscribe($this->getDestination(), array('id' => $id)); 77 | } 78 | 79 | /** 80 | * Set headers 81 | * @return array 82 | */ 83 | protected function getHeaders() 84 | { 85 | $headers = array( 86 | 'id' => $this->getDestination($this->routing_key) . microtime(true) 87 | ); 88 | 89 | if($this->options->has('prefetchSize')) 90 | { 91 | $headers['activemq.prefetchSize'] = $this->options->get('prefetchSize'); 92 | } 93 | 94 | return $headers; 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /ActiveMq/ConsumerInterface.php: -------------------------------------------------------------------------------- 1 | body = $body; 102 | $this->setHeaders($headers); 103 | } 104 | 105 | /** 106 | * Set object with correct headers 107 | * @param array $headers 108 | */ 109 | protected function setHeaders(array $headers) 110 | { 111 | foreach($headers as $key => $value) 112 | { 113 | if(isset($this->$key)) 114 | { 115 | $this->$key = $value; 116 | unset($headers[$key]); 117 | } 118 | 119 | // Clés JMSX 120 | elseif(isset($this->{'JMSX' . $key})) 121 | { 122 | $this->{'JMSX' . $key} = $value; 123 | unset($headers[$key]); 124 | } 125 | } 126 | 127 | $this->headers = new ParameterBag($headers); 128 | } 129 | 130 | /** 131 | * Return header value 132 | * @param string $key 133 | * @return string 134 | */ 135 | public function get($key) 136 | { 137 | return $this->headers->get($key); 138 | } 139 | 140 | /** 141 | * Return body 142 | * @return string 143 | */ 144 | public function getBody() 145 | { 146 | return (string)$this->body; 147 | } 148 | 149 | /** 150 | * Set body 151 | * @param string $body 152 | */ 153 | public function setBody($body) 154 | { 155 | $this->body = $body; 156 | } 157 | 158 | /** 159 | * Return expiration time 160 | * @return int 161 | */ 162 | public function getExpires() 163 | { 164 | return $this->expires; 165 | } 166 | 167 | /** 168 | * Set expiration time 169 | * @param int $expires 170 | */ 171 | public function setExpires($expires) 172 | { 173 | $this->expires = intval($expires); 174 | } 175 | 176 | /** 177 | * Return whether or not the message is persistent 178 | * @return boolean 179 | */ 180 | public function getPersistent() 181 | { 182 | return $this->persistent; 183 | } 184 | 185 | /** 186 | * Set whether or not the message is persistent 187 | * @param boolean $persistent 188 | */ 189 | public function setPersistent($persistent) 190 | { 191 | $this->persistent = (bool)$persistent; 192 | } 193 | 194 | /** 195 | * Return priority on the message 196 | * @return int 197 | */ 198 | public function getPriority() 199 | { 200 | return $this->priority; 201 | } 202 | 203 | /** 204 | * Set priority on the message 205 | * @param int $priority 206 | */ 207 | public function setPriority($priority) 208 | { 209 | $this->priority = intval($priority); 210 | } 211 | 212 | /** 213 | * Get the Message Groups 214 | * @return string 215 | */ 216 | public function getGroupId() 217 | { 218 | return $this->groupId; 219 | } 220 | 221 | /** 222 | * Specifies the Message Groups 223 | * @param string $groupId 224 | */ 225 | public function setGroupId($groupId) 226 | { 227 | $this->groupId = $groupId; 228 | } 229 | 230 | /** 231 | * Reset the group affectation by specify the sequence number to -1 232 | * Next message will be reaffected 233 | */ 234 | public function closeGroup() 235 | { 236 | $this->groupSeq = -1; 237 | } 238 | 239 | /** 240 | * Get the time in milliseconds that a message will wait 241 | * before being scheduled to be delivered by the broker 242 | * @return int 243 | */ 244 | public function getScheduledDelay() 245 | { 246 | return $this->scheduledDelay; 247 | } 248 | 249 | /** 250 | * Set the time in milliseconds that a message will wait 251 | * before being scheduled to be delivered by the broker 252 | * @param int $scheduledDelay 253 | */ 254 | public function setScheduledDelay($scheduledDelay) 255 | { 256 | $this->scheduledDelay = intval($scheduledDelay); 257 | } 258 | 259 | /** 260 | * Get the time in milliseconds to wait after the start time 261 | * to wait before scheduling the message again 262 | * @return int 263 | */ 264 | public function getScheduledPeriod() 265 | { 266 | return $this->scheduledPeriod; 267 | } 268 | 269 | /** 270 | * Set the time in milliseconds to wait after the start time 271 | * to wait before scheduling the message again 272 | * @param int $scheduledPeriod 273 | */ 274 | public function setScheduledPeriod($scheduledPeriod) 275 | { 276 | $this->scheduledPeriod = intval($scheduledPeriod); 277 | } 278 | 279 | /** 280 | * Get the number of times to repeat scheduling a message for delivery 281 | * @return int 282 | */ 283 | public function getScheduledRepeat() 284 | { 285 | return $this->scheduledRepeat; 286 | } 287 | 288 | /** 289 | * Set the number of times to repeat scheduling a message for delivery 290 | * @param int $scheduledRepeat 291 | */ 292 | public function setScheduledRepeat($scheduledRepeat) 293 | { 294 | $this->scheduledRepeat = intval($scheduledRepeat); 295 | } 296 | 297 | /** 298 | * Get Cron entry used to set the schedule 299 | * @return string 300 | */ 301 | public function getScheduledCron() 302 | { 303 | return $this->scheduledCron; 304 | } 305 | 306 | /** 307 | * Use a Cron entry to set the schedule 308 | * @param string $scheduledCron 309 | */ 310 | public function setScheduledCron($scheduledCron) 311 | { 312 | $this->scheduledCron = $scheduledCron; 313 | } 314 | 315 | /** 316 | * Return message Type 317 | * @return string 318 | */ 319 | public function getMessageType() 320 | { 321 | if($this->headers->has('amq-msg-type')) 322 | { 323 | return $this->headers->get('amq-msg-type'); 324 | } 325 | else 326 | { 327 | return self::TYPE_TEXT; 328 | } 329 | } 330 | 331 | /** 332 | * Set message type to text 333 | */ 334 | public function setAsTextMessage() 335 | { 336 | $this->headers->set('amq-msg-type', self::TYPE_TEXT); 337 | } 338 | 339 | /** 340 | * Set message type to bytes 341 | */ 342 | public function setAsBytesMessage() 343 | { 344 | $this->headers->set('amq-msg-type', self::TYPE_BYTES); 345 | } 346 | 347 | /** 348 | * Return message options in header format 349 | * @return array 350 | */ 351 | public function getMessageHeaders() 352 | { 353 | $header = array(); 354 | 355 | // Send only header if default value is changed 356 | if($this->expires != 0) 357 | { 358 | $header['expires'] = 359 | (double)round(microtime(true) * 1000) + $this->expires; 360 | } 361 | 362 | // Stomp message is not persistent by default 363 | if($this->persistent) 364 | { 365 | $header['persistent'] = 'true'; 366 | } 367 | 368 | if($this->priority != 4) 369 | { 370 | $header['priority'] = $this->priority; 371 | } 372 | 373 | if(!is_null($this->groupId) && !empty($this->groupId)) 374 | { 375 | $header['JMSXGroupID'] = $this->groupId; 376 | } 377 | 378 | if($this->groupSeq != 0) 379 | { 380 | $header['JMSXGroupSeq'] = $this->groupSeq; 381 | } 382 | 383 | if($this->scheduledDelay != 0) 384 | { 385 | $header['AMQ_SCHEDULED_DELAY'] = $this->scheduledDelay; 386 | } 387 | 388 | if($this->scheduledPeriod != 0) 389 | { 390 | $header['AMQ_SCHEDULED_PERIOD'] = $this->scheduledPeriod; 391 | } 392 | 393 | if($this->scheduledRepeat != 0) 394 | { 395 | $header['AMQ_SCHEDULED_REPEAT'] = $this->scheduledRepeat; 396 | } 397 | 398 | if(!is_null($this->scheduledCron) && !empty($this->scheduledCron)) 399 | { 400 | $header['AMQ_SCHEDULED_CRON'] = $this->scheduledCron; 401 | } 402 | 403 | // Add additional headers 404 | foreach($this->headers->all() as $key => $var) 405 | { 406 | if(!isset($this->$key)) 407 | { 408 | $header[$key] = $var; 409 | } 410 | } 411 | 412 | return $header; 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /ActiveMq/Publisher.php: -------------------------------------------------------------------------------- 1 | headers->set('routing_key', $routing_key); 33 | } 34 | 35 | $stomp = $this->connection->getConnection(); 36 | 37 | if(!$stomp->send($this->getDestination($routing_key, $concat_key), 38 | $msg->getBody(), 39 | $msg->getMessageHeaders() 40 | )) 41 | { 42 | throw new ActiveMqException('Unable to send message'); 43 | } 44 | 45 | return true; 46 | } 47 | } -------------------------------------------------------------------------------- /Command/ConsumerCommand.php: -------------------------------------------------------------------------------- 1 | consumers[$name] = $consumer; 26 | } 27 | 28 | protected function configure() 29 | { 30 | $this->setName('activemq:consumer') 31 | ->setDescription('Consume a message from a given queue.'); 32 | 33 | $this->addArgument('name', InputArgument::REQUIRED, 'Consumer name'); 34 | $this->addOption('messages', 'm', InputOption::VALUE_REQUIRED, 'Messages to consume', 0); 35 | $this->addOption('route', 'r', InputOption::VALUE_OPTIONAL, 'Routing Key', ''); 36 | } 37 | 38 | protected function execute(InputInterface $input, OutputInterface $output) 39 | { 40 | $name = $input->getArgument('name'); 41 | if (!isset($this->consumers[$name])) { 42 | throw new \InvalidArgumentException(sprintf('Consumer "%s" not found', $name)); 43 | } 44 | $consumer = $this->consumers[$name]; 45 | 46 | $consumer->setRoutingKey($input->getOption('route')); 47 | $consumer->consume($input->getOption('messages')); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Command/ProducerCommand.php: -------------------------------------------------------------------------------- 1 | publishers[$name] = $consumer; 29 | } 30 | 31 | 32 | protected function configure() 33 | { 34 | $this->setName('activemq:producer') 35 | ->setDescription('Send a message to a given queue.'); 36 | 37 | $this->addArgument('name', InputArgument::REQUIRED, 'Producer name') 38 | ->addOption('message', 'm', InputOption::VALUE_REQUIRED, 'Message to send') 39 | ->addOption('serializer', 'z', InputOption::VALUE_REQUIRED, 'Serialize message (serialize, json)') 40 | ->addOption('route', 'r', InputOption::VALUE_OPTIONAL, 'Routing Key', ''); 41 | } 42 | 43 | /** 44 | * Interaction with console 45 | * @param InputInterface $input 46 | * @param OutputInterface $output 47 | */ 48 | protected function interact(InputInterface $input, OutputInterface $output) 49 | { 50 | $questionHelper = $this->getQuestionHelper(); 51 | 52 | if(!$input->getOption('message')) 53 | { 54 | $input->setOption( 55 | 'message', 56 | $questionHelper->ask( 57 | $input, 58 | $output, 59 | new Question('Enter the message to send: ') 60 | )); 61 | } 62 | } 63 | 64 | /** 65 | * Send the message 66 | * @param InputInterface $input 67 | * @param OutputInterface $output 68 | * @return void 69 | */ 70 | protected function execute(InputInterface $input, OutputInterface $output) 71 | { 72 | $time_start = microtime(true); 73 | 74 | $message = $input->getOption('message'); 75 | 76 | if(empty($message)) 77 | { 78 | $output->writeln('Message cannot be empty'); 79 | return; 80 | } 81 | 82 | $name = $input->getArgument('name'); 83 | if (!isset($this->publishers[$name])) { 84 | throw new \InvalidArgumentException(sprintf('Publisher "%s" not found', $name)); 85 | } 86 | $publisher = $this->publishers[$name]; 87 | 88 | // Serializer 89 | switch($input->getOption('serializer')) 90 | { 91 | case 'serialize': 92 | $message = serialize($message); 93 | break; 94 | 95 | case 'json': 96 | $message = json_encode($message); 97 | break; 98 | } 99 | 100 | // Send message 101 | try 102 | { 103 | $msg = new Message($message); 104 | 105 | $publisher->publish($msg, $input->getOption('route')); 106 | $output->writeln( 107 | sprintf( 108 | 'Message has been sent in %s ms', 109 | round(microtime(true) - $time_start, 3) 110 | ) 111 | ); 112 | } 113 | catch(\Exception $e) 114 | { 115 | $output->writeln( 116 | sprintf( 117 | 'Error while sending message: %s', 118 | $e->getMessage() 119 | ) 120 | ); 121 | } 122 | } 123 | 124 | /** 125 | * Replace standard question helper 126 | * @return QuestionHelper 127 | */ 128 | protected function getQuestionHelper() 129 | { 130 | $questionHelper = $this->getHelperSet()->get('question'); 131 | 132 | //@todo Update the Deploy project wich have a strong dependance with this bundle 133 | if (!$questionHelper /*|| get_class($questionHelper) !== 'Overblog\DeployBundle\Command\Helper\DialogHelper'*/) { 134 | $this->getHelperSet()->set($questionHelper = new QuestionHelper()); 135 | } 136 | 137 | return $questionHelper; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | children() 28 | ->arrayNode('connections') 29 | ->useAttributeAsKey('key') 30 | ->requiresAtLeastOneElement() 31 | ->prototype('array') 32 | ->children() 33 | ->scalarNode('user')->defaultNull()->end() 34 | ->scalarNode('password')->defaultNull()->end() 35 | ->scalarNode('version')->defaultValue(1.1)->end() 36 | ->scalarNode('randomize_failover')->defaultFalse()->end() 37 | ->arrayNode('servers') 38 | ->requiresAtLeastOneElement() 39 | ->prototype('array') 40 | ->addDefaultsIfNotSet() 41 | ->children() 42 | ->scalarNode('uri')->defaultValue('localhost:61613')->end() 43 | ->scalarNode('useAsyncSend')->defaultTrue()->end() 44 | ->scalarNode('startupMaxReconnectAttempts')->defaultNull()->end() 45 | ->scalarNode('maxReconnectAttempts')->defaultNull()->end() 46 | ->scalarNode('separator')->defaultValue('.')->end() 47 | ->end() 48 | ->end() 49 | ->end() 50 | ->end() 51 | ->end() 52 | ->end() 53 | ->arrayNode('publishers') 54 | ->useAttributeAsKey('key') 55 | ->prototype('array') 56 | ->addDefaultsIfNotSet() 57 | ->children() 58 | ->scalarNode('connection')->defaultValue('default')->end() 59 | ->arrayNode('options') 60 | ->children() 61 | ->scalarNode('type')->defaultValue('queue')->end() 62 | ->scalarNode('name')->isRequired()->end() 63 | ->end() 64 | ->end() 65 | ->end() 66 | ->end() 67 | ->end() 68 | ->arrayNode('consumers') 69 | ->useAttributeAsKey('key') 70 | ->prototype('array') 71 | ->addDefaultsIfNotSet() 72 | ->children() 73 | ->scalarNode('connection')->defaultValue('default')->end() 74 | ->scalarNode('handler')->isRequired()->end() 75 | ->arrayNode('options') 76 | ->children() 77 | ->scalarNode('type')->defaultValue('queue')->end() 78 | ->scalarNode('name')->isRequired()->end() 79 | ->scalarNode('prefetchSize')->defaultValue(1)->end() 80 | ->end() 81 | ->end() 82 | ->end() 83 | ->end() 84 | ->end() 85 | ->end() 86 | //Connection validation 87 | ->validate() 88 | ->ifTrue( function($v) { 89 | foreach($v['publishers'] as $key => $producer) 90 | { 91 | if(!isset($v['connections'][$producer['connection']])) return true; 92 | } 93 | 94 | return false; 95 | }) 96 | ->thenInvalid('Unknown connection in publishers configuration.') 97 | ->end() 98 | //Connection validation 99 | ->validate() 100 | ->ifTrue( function($v) { 101 | foreach($v['consumers'] as $key => $producer) 102 | { 103 | if(!isset($v['connections'][$producer['connection']])) return true; 104 | } 105 | 106 | return false; 107 | }) 108 | ->thenInvalid('Unknown connection in consumers configuration.') 109 | ->end() 110 | ; 111 | 112 | return $treeBuilder; 113 | } 114 | 115 | /** 116 | * @param TreeBuilder $builder 117 | * @param string|null $name 118 | * @param string $type 119 | * 120 | * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition 121 | */ 122 | private static function getRootNodeWithoutDeprecation(TreeBuilder $builder, $name, $type = 'array') 123 | { 124 | // BC layer for symfony/config 4.1 and older 125 | return \method_exists($builder, 'getRootNode') ? $builder->getRootNode() : $builder->root($name, $type); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /DependencyInjection/OverblogActiveMqExtension.php: -------------------------------------------------------------------------------- 1 | processConfiguration($configuration, $configs); 32 | 33 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 34 | $loader->load('services.yml'); 35 | 36 | // Register connections 37 | foreach($config['connections'] as $name => $connection) { 38 | $this->addConnection($name, $connection, $container); 39 | } 40 | 41 | // Register publishers 42 | foreach($config['publishers'] as $name => $producer) { 43 | $this->addPublisher($name, $producer, $container); 44 | } 45 | 46 | // Register consumers 47 | foreach($config['consumers'] as $name => $consumer) { 48 | $this->addConsumer($name, $consumer, $container); 49 | } 50 | } 51 | 52 | private function addConnection($name, array $connection, ContainerBuilder $container) 53 | { 54 | $definition = new Definition(Connection::class); 55 | $definition 56 | ->addArgument($connection) 57 | ->addTag('activemq.connection') 58 | ; 59 | 60 | $container->setDefinition( 61 | $this->buildConnectionServiceId($name), 62 | $definition 63 | ); 64 | 65 | //@see https://github.com/overblog/ActiveMqBundle/issues/9 66 | $container->setAlias( 67 | $definition->getClass(), 68 | new Alias($this->buildConnectionServiceId($name), true) 69 | ); 70 | } 71 | 72 | private function addPublisher($name, array $publisher, ContainerBuilder $container) 73 | { 74 | $definition = new Definition(Publisher::class); 75 | $definition 76 | ->addArgument(new Reference($this->buildConnectionServiceId($publisher['connection']))) 77 | ->addArgument($publisher['options']) 78 | ->addTag('activemq.publisher'); 79 | $serviceID = sprintf('%s.publisher.%s', $this->getAlias(), $name); 80 | $container->setDefinition($serviceID, $definition); 81 | $container->getDefinition(ProducerCommand::class) 82 | ->addMethodCall('addPublisher', [$name, new Reference($serviceID)]); 83 | 84 | //@see https://github.com/overblog/ActiveMqBundle/issues/9 85 | $container->setAlias($definition->getClass(), new Alias($serviceID, true)); 86 | } 87 | 88 | private function addConsumer($name, array $consumer, ContainerBuilder $container) 89 | { 90 | $definition = new Definition(Consumer::class); 91 | $definition 92 | ->addArgument(new Reference($this->buildConnectionServiceId($consumer['connection']))) 93 | ->addArgument(new Reference($consumer['handler'])) 94 | ->addArgument($consumer['options']) 95 | ->addTag('activemq.consumer'); 96 | $serviceID = sprintf('%s.consumer.%s', $this->getAlias(), $name); 97 | $container->setDefinition($serviceID, $definition); 98 | $container->getDefinition(ConsumerCommand::class) 99 | ->addMethodCall('addConsumer', [$name, new Reference($serviceID)]); 100 | 101 | //@see https://github.com/overblog/ActiveMqBundle/issues/9 102 | $container->setAlias($definition->getClass(), new Alias($serviceID, true)); 103 | 104 | return $definition; 105 | } 106 | 107 | private function buildConnectionServiceId($name) 108 | { 109 | return sprintf('%s.connection.%s', $this->getAlias(), $name); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Exception/ActiveMqException.php: -------------------------------------------------------------------------------- 1 | getContent()); 75 | $publisher->publish($content); 76 | 77 | return new Response('Successful notification', 200); 78 | } 79 | } 80 | ``` 81 | 82 | An example of a consumer: 83 | ```php 84 | =5.6", 14 | "centraldesktop/stomp": "2.0.*", 15 | "symfony/console": "^3.4 || ^4.0", 16 | "symfony/framework-bundle": "^3.4 || ^4.0" 17 | }, 18 | 19 | "autoload": { 20 | "psr-4": {"Overblog\\ActiveMqBundle\\": ""} 21 | } 22 | } 23 | --------------------------------------------------------------------------------