Reputation: 15628
Consider following (wicket) code:
@SpringBean(required=false)
private StatusCheckService service;
In my use case there is no bean of type StatusCheckService in my context. This is not a problem, it is marked as optional so the (wicket) page will initialize just fine.
However:
@SpringBean(name = "statusCheckService", required=false)
private StatusCheckService service;
This fails:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'statusCheckService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:400)
at org.springframework.context.support.AbstractApplicationContext.isSingleton(AbstractApplicationContext.java:1113)
at org.apache.wicket.spring.SpringBeanLocator.isSingletonBean(SpringBeanLocator.java:100)
at org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory.getFieldValue(AnnotProxyFieldValueFactory.java:140)
I would expect it makes no difference. OK, there is no bean with such a name but I marked it as optional so why the exception? Is there any way around this?
Upvotes: 2
Views: 920
Reputation: 843
By doing a usage search in eclipse, you can see that the only time the annotation is queried for its required value is on line 215 of AnnotProxyFieldValue:
if (names.isEmpty())
{
if (annot.required())
{
throw new IllegalStateException("bean of type [" + clazz.getName() + "] not found");
}
return null;
}
Here you can see that the 'required' field of the @SpringBean annotation is only used if the names list (set higher in the function) is empty...
This explains the behaviour you are experiencing, because when you don't specify a name, the names list is empty (because it could not find your class), and null is returned. However when you do specify a name it doesn't bother trying to see if the class exists, and so sends your supplied class-name for spring to look up which proceeds to complain when it cannot find the class.
This could be a bug depending on designers intentions, personally I think if you have specified that the field is not required then the function should return early... If you agree then maybe consider putting in a jira ticket with a quick start.
As for a solution, you haven't mentioned much about your use case, and why you need to set the name even though you do not require the bean to be injected. But assuming you are doing it to dynamically inject the bean based on certain criteria, you could do something like the following: (untested)
In your class where the SpringBean is injected, replace:
@SpringBean(name="statusCheckService", required=false)
private StatusCheckService service;
With:
MyCustomSpringBeanInjector injectedService;
And then MyCustomSpringBeanInjector class is something like:
import org.apache.wicket.injection.Injector;
import org.apache.wicket.spring.injection.annot.SpringBean;
public class MyCustomSpringBeanInjector
{
@SpringBean public StatusCheckService service;
public MyCustomSpringBeanInjector()
{
Injector.get().inject(this);
}
}
Then back in the class where the SpringBean was being injected, put something like:
if(statusCheckServiceRequired)
injectedService = new MyCustomSpringBeanInjector();
and replace "service." with "injectedService.service" where necessary.
Obviously this is a qwik-e fix off the top of my head, and I'm sure there's a better way of doing it, but you get the idea! :)
Best of luck!
Upvotes: 1