2017-02-05 7 views
0

Je configure Spring Rabbit à l'aide d'un fichier xml pour les haricots de printemps et la configuration.Spring Rabbit Queue Xml: NoSuchBeanDefinition lors de l'obtention de la propriété à partir de 'Getter Bean'

Nous utilisons notre propre classe propertyGetter pour récupérer les propriétés. Au printemps le lapin xml ci-dessous, il fonctionne partout sauf pour un endroit. Pourquoi est-ce?

Voici le fichier XML. La méthode 'propertyGetter.get (...)' appelée renvoie une chaîne 'my.queue', mais il semble que l'analyseur xsd de RabbitMq essaie d'obtenir un bean. (?).

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:rabbit="http://www.springframework.org/schema/rabbit" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/rabbit 
     http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd"> 

     <!-- This has the 'propertyGetter' bean --> 
     <import resource="**/applicationContext.xml"/> 

     <!-- RabbitMQ --> 
     <rabbit:connection-factory id="rabbitConnectionFactory" addresses="#{propertyGetter.get('rabbitMq.hostName')}" username="#{propertyGetter.get('rabbitMq.userName')}" password="#{propertyGetter.get('rabbitMq.password')}" virtual-host="#{propertyGetter.get('rabbitMq.vHost')}"/> 
     <rabbit:admin connection-factory="rabbitConnectionFactory"/> 

     <!-- RabbitMQ Template --> 
     <rabbit:template id="rabbitTemplate" connection-factory="rabbitConnectionFactory" message-converter="messageConverter" exchange="#{propertyGetter.get('rabbitMq.exchange')}"/> 


     /******************************************* 
     * 
     * THIS IS THE ONLY PLACE IT DOESN'T WORK 
     * <rabbit:queue name="" 
     *  It does seem to get value 'my.queue' 
     *  but the exception that's posted 
     *  below indicates it's trying to 
     *  construct a bean! Why is this? 
     *******************************************/ 
     <!-- RabbitMQ Queue Definitions --> 
     <!--<rabbit:queue name="my.queue" >--> <!--THIS WORKS--> 
     <rabbit:queue name="#{propertyGetter.get('rabbitMq.queue.name')}" > <!--THIS DOESN'T--> 
      <rabbit:queue-arguments> 
       <entry key="x-ha-policy" value="all"/> 
      </rabbit:queue-arguments> 
     </rabbit:queue> 

     <!-- RabbitMQ Exchange and Binding Definition --> 
     <rabbit:direct-exchange name="#{propertyGetter.get('rabbitMq.exchange')}"> 
      <rabbit:bindings> 
       <rabbit:binding key="#{propertyGetter.get('rabbitMq.routing.key')}" queue="#{propertyGetter.get('rabbitMq.queue.name')}"/> 
      </rabbit:bindings> 
     </rabbit:direct-exchange> 

     <!-- Listeners --> 
     <rabbit:listener-container id="listener" connection-factory="rabbitConnectionFactory" concurrency="3" max-concurrency="5" requeue-rejected="false"> 
      <rabbit:listener ref="eventNotificationAdapter" queues="#{propertyGetter.get('rabbitMq.queue.name')}" priority="#{propertyGetter.get('rabbitMq.queue.priority')}" /> 
     </rabbit:listener-container> 

     <!-- Message Listener Adapters --> 
     <bean id="eventNotificationAdapter" class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter"> 
      <constructor-arg name="delegate" ref="myQueueConsumer"/> 
      <constructor-arg name="messageConverter" ref="messageConverter"/> 
      <property name="defaultListenerMethod" value="process"/> 
     </bean> 

     <bean id="messageConverter" class="org.springframework.amqp.support.converter.JsonMessageConverter"/> 

</beans> 

L'exception lorsque l'application est d'abord initialisé is'NoSuchBeanDefinitionException », mais je ne sais pas pourquoi tout ce qui est l'analyse XML attend un haricot, lorsque l'appel de méthode renvoie une chaîne.

est ici la trace de la pile que je reçois en essayant de déployer l'application:

SEVERE: Exception sending context initialized event to listener instance of class org.jboss.resteasy.plugins.spring.SpringContextLoaderListener 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.amqp.rabbit.config.BindingFactoryBean#0': Cannot resolve reference to bean '#{propertyGetter.get('rabbitMq.queue.name')}' while setting bean property 'destinationQueue'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.queue' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1477) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1222) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:736) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) 
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) 
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) 
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) 
    at org.jboss.resteasy.plugins.spring.SpringContextLoaderListener.contextInitialized(SpringContextLoaderListener.java:48) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5017) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5531) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) 
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) 
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652) 
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1095) 
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1930) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.queue' is defined 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 29 more 

Autres notes: Ceci est un fichier XML qui utilise le ressort-lapin 1.3.xsd

La solution ne n'utilise pas les propriétés du ressort. C'est pour gérer les propriétés d'une autre manière.

+0

Pourriez-vous s'il vous plaît ajouter applicationContext.xml où propertyGetter est initialisé. –

Répondre

1

Ce sont deux choses différentes.

Pour un <bean/>, l'attribut name est un alias pour le nom du bean. Si aucun id n'est fourni, le premier name est utilisé comme ID.

Pour <queue/> l'attribut name est le nom de la file d'attente dans le courtier rabbitmq; le id est toujours le nom du bean et, s'il n'est pas présent, un nom de bean unique est généré.

Il existe une certaine logique pour enregistrer le name comme un alias, mais cela ne fonctionne que lorsque la valeur est connue au moment de l'analyse (comme vous l'avez constaté).

En fait, cette utilisation de l'aliasing est incorrecte et provoque d'autres problèmes - par exemple vous ne pouvez pas avoir un échange et une file d'attente avec le même name - voir this JIRA for a discussion about that.

Pour résoudre ce problème, nous envisageons de supprimer complètement le crénelage et d'exiger un attribut id pour donner un nom au haricot.

Je crois que vous pouvez travailler autour de votre problème en donnant la file d'attente d'un id et le référencement que dans votre conteneur auditeur queues attribut, ou changer le conteneur à utiliser queue-names à la place.

+0

Cela a fonctionné! J'étais encore capable d'utiliser le propertyGetter dans la file d'attente elle-même, mais j'ai simplement ajouté un identifiant et je l'ai aussi utilisé dans le conteneur de l'écouteur pour échanger la liaison. J'ai oublié de mentionner, que le xml dans ma question fonctionne en utilisant un fichier de propriétés et $ {my.prop}. Vous ne savez pas pourquoi cela ne provoque pas la même erreur d'exécution. – Matt

+0

Oui, il existe une logique dans la fabrique de beans pour résoudre les espaces réservés dans les alias, mais il n'y a pas d'équivalent pour les expressions SpEL. –