Element is not allowed here: for qualifier in spring bean definition in IntelliJ - spring

This is the file, I am trying examples from:
http://simplespringtutorial.com/annotations.html
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<bean id="foo" class="annotation.Foo">
<property name="name" value="Daniel"></property>
</bean>
<bean id="anotherFoo" class="annotation.Foo">
<qualifier value="secondaryFoo"></qualifier>
<property name="name" value="Shirley"></property>
</bean>
<bean id="bar" class="annotation.Bar" />
</beans>
This is the Bar class
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Bar {
#Autowired
#Qualifier(value="anotherFoo")
private Foo foo;
#Resource(name="foo")
private Foo foo2;
public void setFoo(Foo foo) {
this.foo = foo;
}
public void printFooName(){
System.out.println(foo.getName());
// System.out.println(foo2.getName());
}
}
This is the test bar which loads the xml file
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFooBar {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"test2.xml");
Bar bar = applicationContext.getBean("bar", Bar.class);
bar.printFooName();
System.out.println(bar.toString());
/*
* if a single definition of a class type exists, then u can get the
* instance by this way also. No need to specify Id
*/
Foo foo = applicationContext.getBean(Foo.class);
System.out.println(foo.getName());
}
}
When I ran the application, the following is the stack trace:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bar': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private annotation.Foo annotation.Bar.foo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [annotation.Foo] 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), #org.springframework.beans.factory.annotation.Qualifier(value=anotherFoo)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at annotation.TestFooBar.main(TestFooBar.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private annotation.Foo annotation.Bar.foo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [annotation.Foo] 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), #org.springframework.beans.factory.annotation.Qualifier(value=anotherFoo)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
... 18 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [annotation.Foo] 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), #org.springframework.beans.factory.annotation.Qualifier(value=anotherFoo)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
... 20 more

Thank you for the extra details, it wasn't immediately obvious what you were trying to do.
The #Qualifier annotation is not meant to be used in the same way as #Resource. When you specify the meta-data <qualifier> element, you are overwriting the identifier that would be used when resolving #Qualifier. In this case, the <qualifier> identifier "secondaryFoo" replaces the <bean> identifier "anotherFoo". If you changed your declaration to
#Autowired
#Qualifier(value = "secondaryFoo")
private Foo foo;
It would be autowired correctly. However, you can still use
Foo anotherFoo = (Foo) applicationContext.getBean("anotherFoo");
to get the <bean> with id "anotherFoo". Although this would fail
Foo anotherFoo = (Foo) applicationContext.getBean("secondaryFoo");
If you are looking for how to autowire based on a unique id, you should use #Resource. The documentation states:
If you intend to express annotation-driven injection by name, do not
primarily use #Autowired, even if is technically capable of referring
to a bean name through #Qualifier values. Instead, use the JSR-250
#Resource annotation, which is semantically defined to identify a
specific target component by its unique name, with the declared type
being irrelevant for the matching process.

Related

Spring's aspectj-autoproxy conflict with Enum factory-method

I have an enum
public enum MyEnum
{
AAA, BBB;
public static final MyEnum findByName(String theName)
{
return MyEnum.valueOf(theName.toUpperCase());
}
}
And I instantiate it as:
<bean id="myEnum" class="xxx.MyEnum" factory-method="findByName">
<constructor-arg value="${someProperties}" />
</bean>
And can inject it easily in other class:
#Autowired(required = true)
#Qualifier("myEnum")
private MyEnum test;
But I need to use proxy for logging things. When I put this to my app context xml:
<aop:aspectj-autoproxy />
The app context would not load, I get this error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [xxx.MyEnum] 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), #org.springframework.beans.factory.annotation.Qualifier(value=myEnum)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 82 more

Why doesn't #Qualifier work with #Autowired?

I have a class like:
#Service
#Qualifier("VeoExecutionService")
public class VeoExecutionService implements ExecutionService {
}
and I use it in a test:
#Autowired
#Qualifier("VeoExecutionService")
private VeoExecutionService veoService;
But when running I get:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.trizic.service.veo.VeoExecutionService com.trizic.service.veo.VeoServiceImportAccountsTest.veoService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.trizic.service.veo.VeoExecutionService] 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), #org.springframework.beans.factory.annotation.Qualifier(value=VeoExecutionService)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 29 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.trizic.service.veo.VeoExecutionService] 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), #org.springframework.beans.factory.annotation.Qualifier(value=VeoExecutionService)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 31 more
I think you should use something like:
#Service("VeoExecutionService")
public class VeoExecutionService implements ExecutionService {
and then, where you inject your service:
#Autowired
#Qualifier("VeoExecutionService")
VeoExecutionService veoExecutionService;
Remember to put <context:annotation-config /> in your xml confing or #AnnotationDrivenConfig in java config.
Note that <context:component-scan /> (#ComponentScan in java config) also activates <context:annotation-config />
I agree gipinani about the first part
#Service("VeoExecutionService")
public class VeoExecutionService implements ExecutionService {
But I think the injection part has to be written this way:
#Autowired
#Qualifier("VeoExecutionService")
Private ExecutionService veoExecutionService;
in order to inject VeoExecutionService implementation of ExecutionService
Try this:
#Autowired
#Qualifier("veoExecutionService")
private VeoExecutionService veoService;
"veoExecutionService" (with lower case v)

Failed to load ApplicationContext in JUnit with JNDI datasource

I have some troubles testing my application, whereas it works well in normal execution.
I think it comes from JNDI resources which are not found, but I don't understand why and how to fix it.
When I start my Junit test, I got this error:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DAOImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDatasource' defined in URL [file:src/test/resources/spring/test-dao-config.xml]: Invocation of init method failed; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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), #org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ..
Here is my configuration:
Context.xml
<Resource name="jdbc/myDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#database:99999:instance"
username="user"
password="password"
validationQuery="select 1 from dual"
testOnBorrow ="true"
maxActive="5"
maxIdle="1"
maxWait="-1" />
test-dao-config.xml
<bean id="myDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDatasource" />
</bean>
DaoImpl
#Repository
public class DacsDAOImpl implements DacsDAO
{
private final static Logger LOGGER = LoggerFactory.getLogger(DAOImpl.class);
#Autowired
#Qualifier("myDatasource")
private DataSource myDatasource;
....
}
And my tests
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/test/resources/spring/test-dao-config.xml" })
public class MyDAOImplTest
{
private MyDAO dao;
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
// builder.bind("java:comp/env/jdbc/myDatasource", "myDatasource");
// builder.activate();
}
#Before
public void setUp() throws IllegalStateException, NamingException
{
dao = new MyDAOImpl();
}
#Test
public void testTotalUser()
{
int result = dao.getTotalUser();
Assert.assertEquals(0, result);
}
}
Thanks
You are running in a test case so everything in your Context.xml isn't available as that is only available on tomcat. Why do you need a jndi lookup in your test case anyway? If you want to test your dao use an in-memory database like hsql, h2 or derby and use that instead. Spring has some nice tags to make it easy for you.
<jdbc:embedded-database id="myDataSource" type="H2">
// Add some init scripts here.
</jdbc:embedded-database>
If you really need to do a JNDI lookup you are almost there in your test case. However you have to register a DataSource not a String. So you still will need to construct some (in-memory) datasource and bind that to the mock jndi location
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// Construct in-memory database
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/myDatasource", myDatasource); //Actual datasource not a String!
builder.activate();
}
And finally your test is also flawed, you are loading your context but aren't doing anything with it. You are constructing a MyDAOImpl in your #Before method. Why even bother loading the context as you are doing nothing with.

Starting asynchronous task via Spring TaskScheduler

I need to execute a task at 7.05am but I am getting an error.
This is the Controller I created.
#Service("myCtr")
public class MyController {
#Autowired
private TaskScheduler scheduler;
#Async
public void executeTaskT() {
scheduler.schedule(new MyWorker(),
new CronTrigger("5 7 * * *"));
}
}
MyWorker is implementing Runnable simply this way:
[...]
#Override
public void run() {
doWork();
}
private void doWork() { [...]
My scheduler configuration file is imported by the web-application-config.xml:
<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-3.1.xsd">
<bean id="TaskScheduler"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
<property name="waitForTasksToCompleteOnShutdown" value="true" />
<property name="poolSize" value="1000" />
</bean>
</beans>
The error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyCtr': Injection
of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not autowire field: private
org.springframework.scheduling.TaskScheduler [...].MyController.scheduler; nested
exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type
[org.springframework.scheduling.TaskScheduler] 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)}
[...]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private
org.springframework.scheduling.TaskScheduler [...].MyController.scheduler; nested
exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type
[org.springframework.scheduling.TaskScheduler] 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)}
[...]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type
[org.springframework.scheduling.TaskScheduler] 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)}
It appears that Spring can't find your TaskScheduler bean.
With INFO logging, you should be able to find your bean definition in the log during initialization. If not, make sure your configuration file is effectively read by doing further tests.
For your precise need, you can also use the following:
#Service
public class MyService {
#Scheduled(cron = "0 5 7 * * *")
public void myMethod() { ... }
}
With this configuration:
<task:annotation-driven scheduler="myScheduler"/>
<task:scheduler id="myScheduler" pool-size="1000"/>
And assuming MyService is properly seen as a bean, using e.g. Component Scan.

'Could not autowire field' exception in Spring

I have a Spring application and am using Spring version 3.0.4.
When I start the server it shows me an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.domain.Custom org.controller.CustomController.custom; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.domain.Custom] 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:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
Code for the domain class
#Entity
#Configurable
#Table(name="tbltest")
public class Custom implements Serializable{
#Autowired
public transient CustomRepository customRepository;
public static CustomRepository getRepository() {
CustomRepository repository = new Custom().CustomRepository;
return repository;
}
#Transactional(readOnly = true)
public static Custom find(final Long id) {
return getRepository().find(id);
}
}
Included configurations in application context
<context:load-time-weaver/>
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="org.domain.custom"/>
Code for my test class:
#Test
#Transactional
public void testCreateNew() {
Custom registration = new Custom("ttt");
Custom.find(1l);
registration.persist();
Assert.assertEquals(true, registration.getId() > 0);
}
Controller
#Controller
#RequestMapping("/custom")
public class CustomController
{
#Autowired
public Custom Custom;
}
And I have added spring-instrument.jar for the VM argument.
Looks like you forgot to add
<context:component-scan base-package="org.domain" />
to your application-context.xml so that spring knows where to scan for your #Component annotations. Just enabling <context:annotation-config /> is not enough.

Resources