Can't get#Autowired to work with beans - java

I'm currently just starting out with Spring and trying to get the hang of it. But I've run into a problem: My #Autowired keeps failing.
In my spring.xml I've got this:
<!--Handle #Autowired-->
<context:annotation-config />
<context:component-scan base-package="org.MYPROJECT">
<context:include-filter type="regex" expression=".*"/>
</context:component-scan>
When running some tests it fails with this (I'm only showing the last exception as its the most important)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.quackbot.dao.AdminDAO] 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.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)
... 50 more
So I try to fix it by adding the bean manually to the config
<bean id="AdminDAO" class="org.quackbot.dao.hibernate.AdminDAOHibernate">
</bean>
Run it again, now I get this
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.quackbot.dao.AdminDAO] is defined: expected single matching bean but found 2: [adminDAOHibernate, AdminDAO]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:796)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
... 50 more
Seems I just can't win when using Spring... First it complains that the beans don't exist, when specifying them it complains that there's too many. What's going on? Why can't it load the correct beans?

Do you have an annotation in your dao?
Something like #Repository or #Component right above the class to tell Spring this needs to be picked up when scanning your base package?

This is more than enough, no other XML configuration is needed in your case:
<context:component-scan base-package="org.quackbot"/>
Secondly, make sure AdminDAOHibernate implements AdminDAO.
Last but not least, double check that the field annotated with #Autowired is of type AdminDAO (interface).
Last piece of advice: add default constructor to AdminDAOHibernate and place place some logging statement there or put breakpoint. There should be only one invocation of this constructor, although it gets tricky when class proxies are involved.

Is this a Spring MVC app? One way or another, I'm guessing you have two separate Spring contexts, whether you know it or not. In one context, you have a dependency on your AdminDAO, but it isn't available, which causes your first exception. Your other context also has a dependency on AdminDAO which is already satisfied, but when you manually add another AdminDAO bean, that fails because there are two of them.

#Autowired using annotations
#Repository("ExampleDao")
public class ExampleDaoImpl implements ExampleDao
#Service("ServiceExample")
public class ExampleServiceImpl implements ExampleService
#Controller
public class ExampleController
#Autowired
private ExmpleService ServiceExample;

Related

Spring Data MongoDb bean xml configuration for repository interface

I have an existing spring application using xml configuration.
Now, I will be using spring-data-mongodb to connect it to a Mongo database.
My repository/dao are all interfaces like:
public interface CustomerDao extends MongoRepository<Customer, String> {
...
}
and inside my service class CustomerService it autowires CustomerDao interface.
<bean id="customerDao" class="com.myapp.repository.CustomerDao" />
<bean id="customerService" class="com.myapp.service.CustomerService">
<property name="customerDao" ref="customerDao"/>
</bean>
but since CustomerDao is an interface, I am always getting the error:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.myapp.repository.CustomerDao]: Specified class is an interface
Based on the tutorials for spring-data-mongodb repositories are mostly interfaces extending to MongoRepository.
My problem is that, I am getting error when autowiring CustomerDao inside CustomerService class if I will not create a bean entry in the xml configuration. Below is the error I am getting:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.myapp.repository.CustomerDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=customerDao)}
You can just specify repositories package location (and custom implementations, if needed).
Then you can just create an interface extending one of the mongo-spring-data repositories (I prefer PagingAndSortignRepository)
After that you'll be able to Autowire your repos.
Don't forget to check component scan package - your repos and services should be there.
And the last thing - check for Spring annotations on your services

Ambiguous autowiring but none with qualifier

I have a service, which injects a Bean with #Autowired as follows.
#Service
public class AdminServiceImpl implements AdminService {
#Autowired
private WebServiceTemplate adminServiceTemplate;
}
And an xml that holds two beans, causing ambiguous autowiring
<bean id="serviceWebClient" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller" />
<!-- More properties -->
</bean>
<bean id="adminServiceWebClient" class="org.springframework.ws.client.core.WebServiceTemplate" scope="prototype">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller" />
<!-- More properties -->
</bean>
This obviously causes the following exception (at startup):
No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] is defined: expected single matching bean but found 2: serviceWebClient,adminServiceWebClient
The weird part:
When I add the #Qualifier in my service to specify which Bean to select, it suddenly can't find any anymore. E.g. I edit my service to the following:
#Service
public class AdminServiceImpl implements AdminService {
#Autowired
#Qualifier("adminServiceWebClient")
private WebServiceTemplate adminServiceTemplate;
}
And instead of getting my specified Bean, I get the following exception message (at a later time when I retrieve the ApplicationContext with context = new ClassPathXmlApplicationContext(CONFIG_FILE);):
No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Is there any logical explanation of something this odd happening? I'm not even sure where to start debugging. It seems to find both, but still refuses to autowire one.
Edit
When removing the additional Bean from my XML and the #Qualifier annotation, I still get:
No qualifying bean of type [org.springframework.ws.client.core.WebServiceTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
But it works fine at startup. It just fails after calling:
context = new ClassPathXmlApplicationContext(CONFIG_FILE);
So at startup it seems to find it (it's required and doesn't fail), but it fails when requesting the context.
Perhaps you are actually starting two application contexts? One would have those beans present while the other wouldn't.
If this is the case, your first context would start okay when the qualifier is present but second one would fail due to the beans missing (exception #2). With no qualifier present, first context would fail to start due to two alternates.
To solve this (when starting second context) give it a parent context:
new ClassPathXmlApplicationContext(new String[]{CONFIG_LOCATION}, parentContext);
I have found out why this problem occurred. And it was a (rather stupid) mistake. In case someone else also runs into this, check out the following:
Overview
I run my application with various Spring Bean files. When my application starts, I use a "main context" file which does a component-scan of my entire base-package. Inside this "main" file I have the WebServiceTemplate Beans.
Startup
My component-scan finds my service and autowires its respectful WebServiceTemplate Bean into it. So it works fine at startup, as expected.
Runtime
When I call
context = new ClassPathXmlApplicationContext(CONFIG_FILE);
I actually call a different file. This file does not contain the WebServiceTemplate Beans but it did also contain a component-scan of the entire base-package. Causing it to find my Service, but not the beans it should autowire.
Solution
When loading the other file, I changed the component-scan to be more narrowed down to just what I need. So it doesn't scan for the service, but it gets loaded at startup.

systemProperties and integrationGlobalProperties conflict

So i have a situation when I need to use spring integration. So I create application context for it and then i describe my all logic in it. But now, I have an error something like this:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [java.util.Properties] is defined: expected single matching bean but found 2: [integrationGlobalProperties, systemProperties]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:800)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1184)
... 61 more
Does someone faced with this problem with systemProperties and integrationGlobalProperties? What does it mean?
P.s. my application context is imported into another application context which has "default-autowire="byType"
As you see your context has two bean of java.util.Properties. That means that you can't inject byType.
Use #Qualifier("systemProperties") to restrict it to specific Properties.
The integrationGlobalProperties isn't only one bean which is populated by Framework. And it isn't a surprise that autowire byType is more and more bad for real applications.
I recently faced same issue. After some research I have decided to wirte a CustomBeanPostProcessor class (implementing BeanFactoryPostProcessor) which will try to find conflicting bean and change its 'autowire' property to 'byName', thus avoiding conflict.
Please have a look at a code below:
public class CustomBeanPostProcessor implements BeanFactoryPostProcessor{
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (beanFactory.containsBean("integrationGlobalProperties")){
//Choose on of the options - either disable autowiring for bean completly,
//or change autowiring type
beanFactory.getBeanDefinition("integrationGlobalProperties").setAutowireCandidate(false);
beanFactory.getBeanDefinition("integrationGlobalProperties").setAttribute("autowire", "byName");
}
}
}
Do not forget to declare this class as Spring bean as well:
<bean class="edu.stackoverflow.spring.misc.CustomBeanPostProcessor"/>

Spring Autowire primitive boolean

My XML configuration includes these bean definitions:
<bean id="abstractFormAction" class="staffing.server.action.form.AbstractFormAction" abstract="true" parent="baseAction">
<property name="volunteerSaver" ref="volunteerSaver"/>
<property name="emailSender" ref="emailSender"/>
<property name="closed" value="${form.closed}"/>
</bean>
<bean id="volunteerFormAction" class="staffing.server.action.form.VolunteerFormAction" parent="abstractFormAction">
<property name="captchaGenerator" ref="captcha"/>
</bean>
Indicating that VolunteerFormAction is a concrete implementation of AbstactFormAction, and will inherit the properties of AbstactFormAction.
In AbstractFormAction, I declare the properties like this:
#Autowired protected VolunteerSaver volunteerSaver;
#Autowired protected EmailSender emailSender;
#Autowired protected boolean closed;
I get the following exception when I try to deploy:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'volunteerFormAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: protected boolean
staffing.server.action.form.AbstractFormAction.closed; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type [boolean] 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 seems to be complaining that it cannot find a bean of byte boolean. But why would it want a bean when have defined property 'closed' by value, not by reference?
You need to use #Value annotation for passing values using property place holders. #Autowire expects a bean of the specified type to be present in the applicationContext.
If you are autowiring the values why are you passing the values int he bean definition? I think what you need is
<bean id="abstractFormAction" class="staffing.server.action.form.AbstractFormAction" abstract="true" parent="baseAction"><bean>
<bean id="volunteerFormAction" class="staffing.server.action.form.VolunteerFormAction" parent="abstractFormAction">
<property name="captchaGenerator" ref="captcha"/>
</bean>
and
#Autowired protected VolunteerSaver volunteerSaver;
#Autowired protected EmailSender emailSender;
#Value("#{form.closed}") protected boolean closed;
If you can use component-scan you need not even specify create the beans
You can add <context:component-scan base-package="<your base package>"/> to your context.xml file and add the annotation #Controller to your controller file
You shouldn't annotate closed with #Autowired.
#Autowired instructs Spring to look up a bean of the type of the autowired field (boolean) in your context, that's why it's complaining about "No matching bean of type [boolean]"
If you inject the value from xml config, there is no need for any annotation on that field.
Based on the code you've shown, it's likely that you have a problem in the way you're loading your Spring contexts. My guess is that you're incorrectly component-scanning your controllers in both the root web application context and in the child context where the controllers are supposed to live. That means there are two instances of this class being created, and only one of them is being configured via the XML. Spring is attempting to autowire the other instance and failing with the given error. You'll find descriptions of the problem and solution in several other SO answers, like these:
Declaring Spring Bean in Parent Context vs Child Context
Spring XML file configuration hierarchy help/explanation
Spring-MVC: What are a "context" and "namespace"?
If you give more detail about your config files and context configuration, someone might be able to point out exactly where you're going wrong.

#autowired #qualifier pointing to a service in a jar file application

I am using another application's service,since everything is already made and done.
My application is to use the interface class inside the application jar.
but something seem to be wrong when this code is called.
BeanFactory factory = new ClassPathXmlApplicationContext( "/Context-Controller.xml");
even if my Context-Controller.xml has this code
<context:component-scan base-package="com.package" />
My error.
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.package.ServiceIamUsing] is
defined: Unsatisfied dependency of
type [interface
com.package.ServiceIamUsing]: expected
at least 1 matching bean
this is how i autowired it on my applciation.
public class MyAppDao implements IMyAppDao {
#Autowired
#Qualifier("serviceIamUsing")
private ServiceIamUsing serviceIamUsing;
//More codes here
}
jay, try the following:
- eliminate the forward-slash "/"
- in your application context xml file, try to import the application context from your external jar file if it has any --> import resource="classpath*:/META-INF/spring/*.xml"
let me know if it does/doesn't work.
Is there, in fact, an instance of ServiceIamUsing in the jar that is also Spring-annotated (#Component, #Service, etc.)? It's possible this is the case, but I'd like to clarify.
If not, does the jar expose a Spring context file you can import, thus adding the additional beans to your context for autowiring?

Categories