I am trying to inject values of a properties file into a controller in a spring mvc project. I am using spring version 5.0.4.
Below is the definition of my servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Step 3: Add support for component scanning -->
<context:component-scan base-package="mu.mra" />
<!-- Step 4: Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Step 5: Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<util:properties id="countryOptions" location="classpath: countries.properties" />
</beans>
the properties file is located in the src/main/resources folder. But unfortunately I am getting the error below
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'studentController': Unsatisfied
dependency expressed through field 'countryOptions'; nested exception
is org.springframework.beans.factory.BeanExpressionException:
Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1021E:
A problem occurred whilst attempting to access the property
'countryOptions': 'Error creating bean with name 'countryOptions':
Invocation of init method failed; nested exception is
java.io.FileNotFoundException: class path resource [
countries.properties] cannot be opened because it does not exist'
I am not too sure about the location of the properties file. Should it be in the WEB-INF folder? I would like some explanation as well on this if possible.
Thanks,
Ashley
You are right, the properties files do exist in the src/main/resources
you can access them as following
<util:properties id="countryOptions" location="classpath:countries.properties" />
Or using the annotations
#Value( "${property.needed}" )
private String property;
So, we have finally managed to update our Spring Framework from version 3.2 to 4.2.25. After some painful processes I am now stuck at this exception: Error creating bean with name 'accountController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException.
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/servlet-context.xml,
/WEB-INF/spring/servlet-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/servlet-context.xml,
/WEB-INF/spring/servlet-security.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
jdbc-context.xml:
<?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:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
">
<context:property-placeholder location="/WEB-INF/spring/spring.properties" />
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare a transaction manager -->
<!-- See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" />
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${app.jdbc.username}"
p:password="${app.jdbc.password}"
p:acquireIncrement="1"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="247"
p:maxStatements="100"
p:minPoolSize="1" />
<bean id="dataSourceSlave" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.slave.jdbc.url}"
p:user="${app.slave.jdbc.username}"
p:password="${app.slave.jdbc.password}"
p:acquireIncrement="1"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="247"
p:maxStatements="100"
p:minPoolSize="1" />
And a full exception printStack():
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'accountController': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'accountService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'friendService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'agentProfileService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'screenNameService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'exceptionService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mailService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'emailNotificationService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sportProfileService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'countryService': Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSourceSlave' defined in
ServletContext resource [/WEB-INF/spring/jdbc-context.xml]:
Error setting property values; nested exception is
org.springframework.beans.NotWritablePropertyException:
Invalid property 'acquireIncrement' of bean class
[org.springframework.jdbc.datasource.DriverManagerDataSource]:
Bean property 'acquireIncrement' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:311)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5068)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5584)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:875)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1259)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1998)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Not sure if relevant: I am using javax.servlet-api-3.1.
And now AccountService.java:
#Service("accountService")
#Transactional
public class AccountService
{
protected static Logger log = LogManager.getLogger(AccountService.class);
private NamedParameterJdbcTemplate jdbcTemplate;
private SimpleJdbcInsert jdbcInviteInsert;
private SimpleJdbcInsert jdbcChallengeInsert;
private SimpleJdbcInsert jdbcPostitInsert;
private SimpleJdbcInsert jdbcPreferenceInsert;
#Resource(name = "dataSource")
public void setDataSource(DataSource dataSource)
{
this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.jdbcInviteInsert = new SimpleJdbcInsert(dataSource).withTableName("invite_contact").usingGeneratedKeyColumns("id");
this.jdbcChallengeInsert = new SimpleJdbcInsert(dataSource).withTableName("challenge").usingGeneratedKeyColumns("id");
this.jdbcPreferenceInsert = new SimpleJdbcInsert(dataSource).withTableName("preference").usingGeneratedKeyColumns("id");
this.jdbcPostitInsert = new SimpleJdbcInsert(dataSource).withTableName("account_postit");
}
// super-awesome-revolutionary code
}
If there is any additional information I should provide, please let me know :)
DriverManagerDataSurce does not provide pooling capabilities. It does not define the properties acquireIncrement ,idleConnectionTestPeriod, maxPoolSize ,maxStatements and minPoolSize.
Either remove these properties or use a datasource that supports pooling eg apache commons-dbcp BasicDataSource. DriverManagerDataSurce is not recommed for use in production systems. Its for testing purposes.
For example
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
</bean>
The root cause is
No bean named 'dataSourceSlave' is defined
Seems like somewhere inside service you reference it by this name, while the datasource bean is created with name 'dataSource'.
Check your servlet-context.xml to see if you are scanning the package where your controller are and then check if you have something like this:
<context:component-scan base-package="your/package/path/controllers"/>
your/package/path/controllers is where your controller class are living.
how to import Java Config bean in XML Config?
I try to create sample like this :
package com.fanjavaid.javaconfig;
...
#Configuration
public class CDConfig {
#Bean
public CompactDisc compactDisc() {
return new ParaPencariTuhan("Insya Allah", "Ungu");
}
}
And here is my XML Config :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- <import resource="cd-config.xml"/> -->
<bean class="com.fanjavaid.javaconfig.CDConfig" />
<bean id="cdPlayer" class="com.fanjavaid.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
</beans>
But when i run i get this following error :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cdPlayer' defined in class path resource [spring-config.xml]: Cannot resolve reference to bean 'compactDisc' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'compactDisc' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:646)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at AppXMLConfig.main(AppXMLConfig.java:21)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'compactDisc' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:641)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1159)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:282)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
... 17 more
Example that I made to follow the book Spring in Action.
What's the solution?
Thank you very much. :)
According to M.Denium answer, it works now.
Just add :
<context:annotation-config />
in Spring XML Configuration. So, it will looks like this :
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config />
<bean class="com.fanjavaid.config.CDConfig" />
<bean id="cdPlayer" class="com.fanjavaid.spring.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
</beans>
Thank you very much ^^,
I'm having a bad time trying to run my program using Spring #Autowired annotation.
Just to explain you what I'm trying to do, I have a main controller class, MainController, that always uses two other classes (SquadraController class and UserController class) to do some work.
Instead of instantiating these classes any time I need them, I decided to declare them as instance variables with the #Autowired annotation and call them any time I need them.
So I have my instance variables with #Autowired annotation and declared the beans in the context xml file, but I get the following error and I can't get out of it:
20/03/2015 15:10:00 - WARN - (AbstractApplicationContext.java:487) - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.fabrizio.fantavalcanneto.controller.UserController org.fabrizio.fantavalcanneto.controller.MainController.userController; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.fabrizio.fantavalcanneto.controller.UserController] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:663)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:629)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:677)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:548)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:489)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
This is my MainController class (the snippet that raises the error):
#Controller
public class MainController {
private static final Logger logger = LoggerFactory.getLogger(MainController.class);
#Autowired
private UserController userController;
#Autowired
private SquadraController squadraController;
This is the xml file where I declare my beans (I also tried to declare MainController bean without declaring the instance variables as properties):
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="org.fabrizio.fantavalcanneto.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="userController" class="org.fabrizio.fantavalcanneto.controller.UserController" >
</bean>
<bean id="mainController" class="org.fabrizio.fantavalcanneto.controller.MainController">
<property name="userController" value="userController"></property>
<property name="squadraController" value="squadraController"></property>
</bean>
<bean id="squadraController" class="org.fabrizio.fantavalcanneto.controller.SquadraController">
</bean>
</beans>
UserController and SquadraController have no instance variables.
If you are context component scanning you don't need to define the beans in the config file, something like this will work. All you need is #Controller annoation on the relevant classes :
<context:component-scan base-package="org.fabrizio.fantavalcanneto.controller" />
// for default converters etc add this aswell
<mvc:annotation-driven/>
Just check you have the correct base package/typos
I have classes, xml configuration file and error stack trace like this. I have no idea why #Qualifier doesn't work. I see on errors that he don't even do anything.
DOG
public class SimpleDog implements Dog {
#Autowired
#Qualifier("small")
private Size size;
private String name;
public Size getSize() {
return size;
}
public void setSize(Size size) {
this.size = size;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void giveSound() {
System.out.println("dog size is : width : (" + size.getWidth() + ") , height : (" + size.getHeight() + ")");
System.out.println("dog's name : " + name);
}
}
TEST CLASS
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-test2.xml");
SimpleDog dog = (SimpleDog) context.getBean("dog");
dog.giveSound();
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.tests.test2.SimpleDog">
<property name="name" value="Puppy" />
</bean>
<bean id="size1" class="com.tests.test2.Size">
<qualifier value="small"/>
<property name="height" value="2"/>
<property name="width" value="1"/>
</bean>
<bean id="size2" class="com.tests.test2.Size">
<qualifier value="large"/>
<property name="height" value="20"/>
<property name="width" value="10"/>
</bean>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>
Error Stack Trace
WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dog': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
at pl.patrykgryta.test2.Test2.main(Test2.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 18 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1016)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
... 20 more
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dog': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
at pl.patrykgryta.test2.Test2.main(Test2.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 18 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1016)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
... 20 more
Need help
Probably your ApplicationContext's BeanFactory is configured with default AutowireCandidateResolver (i.e. SimpleAutowireCandidateResolver) instead of QualifierAnnotationAutowireCandidateResolver.
In previous versions of Spring (before 4.0), QualifierAnnotationAutowireCandidateResolver was set during creation of most ApplicationContexts (compare AbstractRefreshableApplicationContext.customizeBeanFactory(DefaultListableBeanFactory) implementations).
Currently, QualifierAnnotationAutowireCandidateResolver for AppCtx is/can be applied by:
org.springframework.beans.factory.annotation.CustomAutowireConfigurer (see javadoc and implementation of postProcessBeanFactory(ConfigurableListableBeanFactory) method), e.g. add to your xml:
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
<context:annotation-config /> (see: AnnotationConfigBeanDefinitionParser.parse(Element,ParserContext) and related)
#Qualifier is used to reference a bean by its name or id. Since it can't find an xml entry that has a name or id of 'small' it tries to match by type, of which it found two instances of Size.
The following would work:
<bean id="small" class="com.tests.test2.Size">
<property name="height" value="2"/>
<property name="width" value="1"/>
</bean>
Though it appears you would like to treat instances of Size as pre-configured beans. If that were the case you could declare instances of Dog in your xml file and refer to Size beans ... something like this:
<bean id="rex" class="com.tests.test2.SimpleDog">
<property name="name" value="Puppy" />
<property name="size" ref="size1"/>
</bean>
#Qualifier(name="..") annotation and give the name of the bean that we want Spring to inject
and name of your beans are size1 and size2 .
so try
#Qualifier("size1")
#Qualifier("small") means you look for a bean named "small" (bean id="small" ...) #Autowired means you look for a bean with a type that matchs.
It makes sense to use this two configurations together in some cases. It means: look for a bean named like that, and if you don't find, then look for a bean with the correct type. This can be powerful, very.
From the Spring documentation, you can declare who is "small" with an xml qualifier, as you did. But in their example there is NO id="..." I don't know if it makes sense to define both qualifier and id. So I suppose (I don't test) you can repair your example by removing the parts id="sizeX"
As says your stacktrace
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
Spring can't match a single bean to inject because he find 2 beans that could using, for this reason will thrown this exception.
Exception thrown when a BeanFactory is asked for a bean instance for
which multiple matching candidates have been found when only one
matching bean was expected.
Reference of Exception
Anyway you're using this thing in the wrong way, because there isn't any bean with id="small"
You must change #Qualifier("small") to #Qualifier("size1") or #Qualifier("size2").
In Spring 4.x you should work with the following XML schema in order for this to work for you:
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
and you should add the following tag:
<context:component-scan base-package="com.tests.test2" />
So the following XML should solve your problem (it solved mine :) ):
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.tests.test2" />
<bean id="dog" class="com.tests.test2.SimpleDog">
<property name="name" value="Puppy" />
</bean>
<bean id="size1" class="com.tests.test2.Size">
<qualifier value="small"/>
<property name="height" value="2"/>
<property name="width" value="1"/>
</bean>
<bean id="size2" class="com.tests.test2.Size">
<qualifier value="large"/>
<property name="height" value="20"/>
<property name="width" value="10"/>
</bean>
</beans>
See more here.
We have struts 1.x used with Spring 3.x in our project. In the process of upgrading from spring 3->4, our qualifier annotation in the struts action does not work any more. After digging in and compare the Spring 3 and 4, finally found the reason.
reason1: QualifierAnnotationAutowireCandidateResolver is not the default resolver in spring 4
In Spring 3, after we create our beanfacotry in the application context, Spring will explicitly call :
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
In spring 4, it is not called any more in the AbstractRefreshableApplicationContext’s
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)
So for the parent(root) context, it should still work as is if you have the in the config xml. However for the child context the default resolver will become ‘SimpleAutowireCandidateResolver’
reason2: The child resolver is passed to parent when trying to determine ‘isAutowireCandidate()’ in Spring 4’s DefaultListableBeanFactory
The isAutowireCandidate() will delegate the responsibility to parent beanFactory if it cannot make decision.
In Spring 3, the delegation does not pass the resolver to the parent so that parent context uses its own resolver to call the isAutowireCandidate(). However in Spring 4, it changes. The resolver is passed as a parameter to the parent who uses it to call the isAutowireCandidate(). So even the parent has a ContextAnnotationAutowireCandidateResolver which extends QualifierAnnotationAutowireCandidateResolver as its resolver, it still does not help.
The #a5phyx solution should work if it is added to the child's application context xml.
Try using this bean definition in your beans.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<context:annotation-config/>
<!-- define your beans here-->
</beans>