0

Does anyone know how the process for getting a bean differs between using @Resource and getBean? Right now I have a situation where this works:

@Autowired
ApplicationContext applicationContext

public void test() {
    Object x = this.applicationContext.getBean("beanName"); //this returns the object I want
}

But this doesn't:

@Resource(name="beanName")
Object x; //"beanName" can't be found

I'd like to understand how these two processes differ so I can begin to understand what my error is.

The stacktrace for the second example. mainBean is a component-scanned bean with nothing else in it besides the code I posted.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainBean': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'beanName' is defined
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    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: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:385)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1718)
    at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:385)
    at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:299)
    ... 97 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'beanName' 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.doGetBean(AbstractBeanFactory.java:277)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:549)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
user886596
  • 2,380
  • 5
  • 31
  • 53
  • 1
    Please post the full exception stack trace for your second snippet. – Sotirios Delimanolis Feb 17 '14 at 20:35
  • 1
    Does this help you? http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/. It explains how `@Resource`, `@Inject` and `@Autowired` resolve a dependency, but it is kind of long to elaborate in an answer and I do not feel to summarize as long as the link is available. Plus, without more info (stacktrace, configuration, etc) I can't be more helpful now! – ThanksForAllTheFish Feb 17 '14 at 20:37
  • 1
    Where are these injection targets located? Which classes? Show us the bigger picture. – Sotirios Delimanolis Feb 17 '14 at 20:44
  • Works as expected for me. You must be doing something else in between what you are showing us. – Sotirios Delimanolis Feb 17 '14 at 21:04
  • @SotiriosDelimanolis I'm just trying to get some ideas as to how this could be even be possible (short of changing Spring source code). Lets say if you were purposely trying to break Spring and cause this scenario, do you have any ideas on how this could be done? That in itself would be satisfactory to me as an answer. – user886596 Feb 17 '14 at 21:13
  • You haven't shown how you load either bean, so it's possible you are loading one bean where a bean named `beanName` exists and the other in a context where a bean named `beanName` doesn't exist. – Sotirios Delimanolis Feb 17 '14 at 21:14
  • @SotiriosDelimanolis Not sure what you mean by "load either bean", but `beanName` is only defined on only one XML file in the whole app. It is not being component scanned. In both scenario 1 and 2, the mainBean is being defined in the same place, and called in the same way. – user886596 Feb 17 '14 at 21:24
  • Can you show the XML where you are creating the bean and the class where you are retrieving it? – ThanksForAllTheFish Feb 17 '14 at 21:26
  • Give us a minimal configuration and and driver ( a main method for example) that would reproduce what you see. – Sotirios Delimanolis Feb 17 '14 at 21:40

1 Answers1

1

Both annotations work via a bean post-processor that needs to be applied in the same context as the annotated bean (see reference here):

  • @Autowired works via AutowiredAnnotationBeanPostProcessor
  • @Resource (as well as other annotations) works via CommonAnnotationBeanPostProcessor

So the behaviour you see means that the CommonAnnotationBeanPostProcessor is not being applied to the bean where @Resource is being used.

The CommonAnnotationBeanPostProcessor can be activated by either:

  • adding it explicitly as a bean to that particular context
  • via <context:annotation-config>
  • via <context-annotation-scan>

Note that this needs to be done in the same spring context as the bean using @Resource.

Spring applications can have multiple contexts, for example one root context and multiple servlet dispatcher contexts, see also this answer.

So make sure to apply the bean post processor on the same context where the bean using @Resource is defined.

Community
  • 1
  • 1
Angular University
  • 42,341
  • 15
  • 74
  • 81