guessCheck
guessCheck

Reputation: 13

Spring Bean Creation at Runtime

I'm trying to create beans at runtime by using the @Configuration and the @Bean annotations. The reason for this is I am trying to have Spring be aware of the created beans so that it can handle scheduling for the application I am creating. I've defined the annotated class like so:

@Configuration  
public class GathererConfigBean {
    @Bean(name = "FactoryBean")
    public MethodInvokingJobDetailFactoryBean createMethodInvokingJobDetail(String service, Object obj, String method) throws ClassNotFoundException, NoSuchMethodException{
        MethodInvokingJobDetailFactoryBean jobDetailFactory = new MethodInvokingJobDetailFactoryBean();
        jobDetailFactory.setBeanName(service + "FactoryBean");
        jobDetailFactory.setTargetObject(obj);
        jobDetailFactory.setTargetMethod(method);
        jobDetailFactory.setConcurrent(false);
        jobDetailFactory.afterPropertiesSet();
        return jobDetailFactory;
    }

    @Bean(name = "TriggerBean")
    public CronTriggerBean createTriggerBean(String service, JobDetail job, String schedule) throws ParseException{
        CronTriggerBean trigger = new CronTriggerBean();
        trigger.setBeanName(service + "TriggerBean");
        trigger.setJobDetail(job);
        trigger.setCronExpression(schedule);
        return trigger;
    }

    public CronTrigger createTrigger(String service, JobDetail job, String schedule) throws ParseException{
        return createTriggerBean(service, job, schedule);
    }

    public JobDetail createJobDetail(String service, AbstractGatherer obj, String method) throws ClassNotFoundException, NoSuchMethodException{
        return (JobDetail) createMethodInvokingJobDetail(service, obj, method).getObject();
    }
}

The problem is that when I run this I always get the following exceptions and I have been unable to find a similar example of what I am doing on-line. Originally, I had thought it was because they have the same name, but that doesn't seem to be the case because when I just run one I get the same error.

    Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'FactoryBean' defined in class path resource [com/linuxbox/enkive/statistics/gathering/GathererConfigBean.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: : No matching bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Related cause: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'FactoryBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:461)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:983)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:879)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    at com.linuxbox.enkive.Main.run(Main.java:54)
    at com.linuxbox.enkive.MainJettyWebApps.main(MainJettyWebApps.java:53)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    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.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723)
    ... 16 more
Related cause:
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'FactoryBean': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:297)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getTypeForFactoryBean(AbstractBeanFactory.java:1343)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:678)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:507)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:317)
    at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:185)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:829)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:461)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:983)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:879)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    at com.linuxbox.enkive.Main.run(Main.java:54)
    at com.linuxbox.enkive.MainJettyWebApps.main(MainJettyWebApps.java:53)

Any help, feedback, ideas, or suggestions would be greatly appreciated, and let me know if you need more specific information!

Upvotes: 1

Views: 5095

Answers (2)

Japan Trivedi
Japan Trivedi

Reputation: 4483

I suggest you to use @PostConstruct annotation on one of your method that needs to be executed just after the dependency injection is performed. Have a look at this link to know more about it.

One more way is to make your class implement ApplicationContextAware interface to get access to the application context. For more details on it please refer this link.

Hope this helps you. Cheers.

Upvotes: 1

krock
krock

Reputation: 29629

It looks like spring is having trouble resolving your String parameters for your Bean methods. Have a look at the spring documentation where they construct a datasource using JavaConfig. As the examples suggest you should try using @Qualifier

@Autowired @Qualifier("quartz.service.name") String service;
// ...

or @Value with a SpEL expression to bind the string params

@Value("${quartz.service.name"}) String service;

The spring documentation does not provide examples of using @Autowired @Qualifier as method parameter annotations with JavaConfig but it should be consistent with constructor autowiring.

Upvotes: 0

Related Questions