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"/>
Related
I am trying to add a new Spring bean to one of my projects. The bean is defined and created in another package like so:
#Configuration
public class UtilityBeans {
public static String MY_BEAN_NAME = "my.bean.name";
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
}
I use it in my other package like this:
#Configuration
#Import({
UtilityBeans.class
)}
...
#Resource(name = UtilityBeans.MY_BEAN_NAME)
private MyUtilBeanClass myUtilBeans;
During runtime I get:
ERROR
Caused by: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'my.bean.name': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
...
The logs do not give me any useful information as the stack trace is all in Spring library. How can I find out what failed? Is it incorrect usage of resource or is it that the bean creation itself is wrong?
I am using Spring-4 with JDK8.
The issue here was that the bean was being created in 2 different points in my spring configuration due to some refactoring and the fix was to remove duplicate code. I had the same bean creation code:
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
... in another class I had half way refactored.
In this case my mistake was that I did not grep across all the log files being generated. The exceptions were being split and then buried into 2 different logs, one for a server start up and one for application runtime. The above exception was being posted to the application log. The other logs contained the relevant exception which stated that duplicate bean creation failed and the fix was to remove duplicate code.
I am sorry that this is probably too vague and generel of a question. I am trying to bring up a huge legacy project with tons of spring wirings, and I am getting this error:
The bizzare thing is this error does not tell me on which xml, which bean id, the error occurs.
I certainly don't expect anybody to point me to where to fix.. My question is, how do spring experts even debug this kind of uninformative error message?
Yes, I understand it must be one of my xml bean was set wrongly. But shouldn't the error message make it easier for me to find out which bean?
Any advice would be extremely appreciated.
00:09:00.640 [main] ERROR com.xxxx.yyyy.zzzzzz.AppMain - Failed to initialize BLAH BLAH BLAH
java.lang.IllegalStateException: No bean class specified on bean definition
at org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass(AbstractBeanDefinition.java:381) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:154) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1035) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:939) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
It's thrown by following piece of code. The init() methods takes in the spring xml files and do its wiring.
try {
AppMain.init(args_);
} catch (Exception e) {
_LOGGER.error("Failed to initialize BLAH BLAH BLAH", e);
System.exit(-1);
}
That's a piece of the sources where it fails
You can try to set a breakpoint there in the Exception throwing. Or add the spring code rather than jar file and try to debug there.
public Class<?> getBeanClass() throws IllegalStateException {
Object beanClassObject = this.beanClass;
if (beanClassObject == null) {
throw new IllegalStateException("No bean class specified on bean definition");
}
if (!(beanClassObject instanceof Class)) {
throw new IllegalStateException(
"Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
}
return (Class) beanClassObject;
}
My question is, how do spring experts even debug this kind of
uninformative error message?
I'd argue that the error message is very informative. It states that something has tried to put your application in an illegal state. In this particular example, your context was configured in a way where some bean's class is not specified. This is typically caused by forgetting to put a class attribute in a <bean> declaration.
Spring creates BeanDefinition objects for each bean in your context. These can be from your <bean> declarations or other XML elements or Java configuration elements (from #Configuration, #Component, etc.). Almost everything involved in a Spring ApplicationContext is a bean.
You can be pretty sure that Spring's infrastructure beans aren't to blame for this. Spring is an established framework with tons of work put into it and testing done before every release. The immediately obvious alternative is that somewhere in your code you forgot to specify a class. Did you, for example, try to make an abstract <bean> but forget to add the abstract="true"? Did you register a BeanDefinitionParser and create BeanDefinitions without a class? Did you create BeanDefinitionPostProcessor and remove BeanDefinition class values?
Those are the things I would start with.
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;
What exactly causes this?
org.springframework.beans.factory.NoSuchBeanDefinitionException: \
No unique bean of type [fi.utu.keycard.business.KeyCardManager] \
is defined: expected single matching bean but found 2: \
[dataBaseTarget, database]
// etc. (rest of Stack Trace is irrelevant)
What I need is autowiring 3 things: validator, ldap connection and database connection.
I call it:
#Controller
Controller(KeyCardManager database,
LdapPersonDao personManager,
GiveFormValidator validator)
The error seems to cause by another bean, if I change the order of these parameters. I have no signing-in, so I dont have UserDetails or so.
The fix is probably something like this:
public Controller(
#Qualifier("beanQualifier") KeyCardManager database,
LdapPersonDao personManager,
GiveFormValidator validator
)
Since there are apparently two beans of type KeyCardManager in your application context, you need to tell the context which one to wire.
Unfortunately the #Qualifier mechanism doesn't work with bean names, you must either annotate the actual bean with a corresponding #Qualifier or add a <qualifier> element to the XML bean definition.
The #Resource annotation works with bean names, but it doesn't support Constructor parameters (that's not Spring's fault, it's a JSR-250 standard annotation with #Target({TYPE, FIELD, METHOD}))
Reference:
Autowiring Collaborators
Fine-tuning annotation-based
autowiring with qualifiers
Troubleshooting
If you don't know why there are two beans of the same type in the context, first of all navigate to the bean interface (I assume KeyCardManager is an interface, if not, do the same thing for the class anyway) and if you use Eclipse select Navigate > Open Type Hierarchy. If you find more than one concrete class that inherits from KeyCardManager (including KeyCardManager itself), then there's probably your problem.
If that is not the case, you probably have two beans of the same type in your application context. One way that can happen is when you define a bean through both XML and classpath scanning. I.e. if you have this line in your XML:
<context:component-scan base-package="org.example"/>
Make sure you don't manually wire any beans from the org.example package (or you will have double beans, which can lead to the problem you have).
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [fi.utu.keycard.business.KeyCardManager] is defined: expected single matching bean but found 2: [dataBaseTarget, database]
It seems you are autowiring by class type. but there are multiple bean available in the context with same class. which are dataBase & dataBaseTarget
byType
Allows a property to be autowired if
there is exactly one bean of the
property type in the container. If
there is more than one, a fatal
exception is thrown, and this
indicates that you may not use byType
autowiring for that bean. If there are
no matching beans, nothing happens;
the property is not set. If this is
not desirable, setting the
dependency-check="objects" attribute
value specifies that an error should
be thrown in this case.
Document
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?