1

I was using Provider to create prototype beans(with @Autowired fields) in a for loop

But it seems, Provider is not playing well with Spring Framework

Whenever I try to execute Provider get() method, the Spring Autowired Environment Bean is not injected

I suspect that when calling get(), we're getting JSR330 managed Bean and not Spring Managed Bean

Look at the Snippets

BeanClass.java

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BeanClass implements Iface {
    @Autowired
    private Environment env;
    @Override
    public void doit() {
        System.out.println("hoo hoo "+env.getProperty("propkey"));
    }
}

Classy.java

@Component
public class Classy {
    @Autowired
    private Provider<Iface> ifaceProvider;
    public void doit_general() {
        for(int i=0;i<2;i++) {
            Iface if = ifaceProvider.get();
            if.doit();
        }
    }
}

When I execute this, I get an Error specifying that "environment" bean is not available

Or should I use @Inject in-place of @Autowired? I'm not so sure...

Any Spring Sensei who can clarify this and provide a Solution?

Stacktrace:

StackTrace: ----
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DBXMLToTransImpl': Unsatisfied dependency expressed through field 'dbconn'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'oracleDBConnection': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getObject(DefaultListableBeanFactory.java:1630)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory$Jsr330DependencyProvider.get(DefaultListableBeanFactory.java:1699)
    at tpt.process.routers.ADImportOperationRouter.route(ADImportOperationRouter.java:110)
    at tpt.process.routers.ADImportOperationRouter.run(ADImportOperationRouter.java:159)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'oracleDBConnection': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 14 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$ShortcutDependencyDescriptor.resolveShortcut(AutowiredAnnotationBeanPostProcessor.java:740)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1077)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:548)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$200(AutowiredAnnotationBeanPostProcessor.java:117)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:577)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    ... 25 more

Update:

This is strange... When I created a dummy code and replicated the same, The Environment got injected properly in the @Autowired field...

Refer: Threaded Beans and Autowiring for more Details

Crystal Paladin
  • 579
  • 5
  • 26
  • It doesn't matter what you're using `@Autowired` or `@Inject`, they are equal. – Bohdan Levchenko Jul 12 '17 at 14:26
  • Your code is correct. Which version of spring are you using? – Bohdan Levchenko Jul 12 '17 at 14:26
  • @BohdanLevchenko, Spring Version `4.3.9.RELEASE` and JSR330 `javax.inject version 1` – Crystal Paladin Jul 13 '17 at 04:32
  • Well, it should work fine, please add a stacktrace to your question – Bohdan Levchenko Jul 13 '17 at 06:04
  • @BohdanLevchenko, Included the Stack Trace... When I created a dummy code to check the Environment Being Autowired, it worked... but in the main code, i got the error... May be if we extend an abstract class, Environment is not injected? I'll check the dummy code with extending Abstract class – Crystal Paladin Jul 13 '17 at 07:10
  • Looks very strange, can you try defining environment bean manually like: `@Bean Environment environment(ApplicationContext context) { return context.getEnvironment();}` ? – Bohdan Levchenko Jul 13 '17 at 07:56
  • @BohdanLevchenko, When I include `@Bean public Environment environment(ApplicationContext context) { return context.getEnvironment(); }` in the Configuration class, the environment is injected and it works fine... but isn't it bad to use Application Context inside the Classes other than the main method... Coz it's Inversion of Inversion of Control... – Crystal Paladin Jul 13 '17 at 08:22
  • Is it because of the `@Bean public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() { return new PropertySourcesPlaceholderConfigurer(); }` line in configuration class that the Environment is not injected? perhaps... Just a thought – Crystal Paladin Jul 13 '17 at 08:23
  • 1
    Using `ApplicationContext` or any spring specific classes in **configurations** is perfectly normal since configurations are already coupled to spring. But anyway try to locate the bean which prevents normal injection of `Environment` – Bohdan Levchenko Jul 13 '17 at 08:28
  • @BohdanLevchenko, I just found it... A bug in Spring Framework(may be I'm exaggerating)... When we use a thread, the Application context closes the resources and when the thread tries to access the Environment resource(using provider), it ends up with nothing... – Crystal Paladin Jul 13 '17 at 09:20
  • Well, it happens) Feel free to open a jira issue if you think it is a bug, it might help somebody in the future :) – Bohdan Levchenko Jul 13 '17 at 09:25

0 Answers0