|
|
Accessing parent beans in JavaConfig
Hi, folks!
I am trying to configure Spring Batch using JavaConfig.
In XML I have the following configuration:
Code: lt;bean id=quot;jobTokenizerquot; parent=quot;tokenizerquot;gt; lt;property name=quot;namesquot; value=quot;...quot;/gt; lt;/beangt;
This bean, actually refers to its parent (previously configured as abstract in another XML) and adds it another property.
From chapter 5.6 of the JavaConfig reference documentation I have learned that I should declare child bean as static nested class. That effectively means that I can't access the parent bean (since the parent bean declaration method is not static):
Code:
@Configuration
public class JobsConfig {
//parent @Bean public DelimitedLineTokenizer tokenizer() { return new DelimitedLineTokenizer(fileDelimiter()); }
@Configuration public static class SpecificJobConfig {
@Bean public DelimitedLineTokenizer jobTokenizer() { //This line does not compile!DelimitedLineTokenizer tokenizer = tokenizer();tokenizer.setNames(new String[]{...});return tokenizer; } }
}
Probably, I am missing something. I am sure that one Spring service can configure another one, can't it?
Thanks in advance.
Baruch.
Hi Baruch,
Section 5.6 points out that in the case of nested @Configuration classes, the declaring class will be treated as a parent application context. This is quite different than the semantics of bean definition inheritance, though they incidentally both use 'parent' terminology. Rather than explaining the details of the differences, let me modify your code snippet just a bit, and let's see if it will achieve what you're looking for:Code:
@Configuration
public class JobsConfig { @Bean public DelimitedLineTokenizer tokenizer() { return new DelimitedLineTokenizer(fileDelimiter()); }
}
@Configuration
public class SpecificJobConfig extends JobsConfig {
@Bean public DelimitedLineTokenizer jobTokenizer() { DelimitedLineTokenizer tokenizer = tokenizer(); tokenizer.setNames(new String[]{...}); return tokenizer; }
}
Perhaps the simplest solution is just to use basic class inheritance. In the example above, SpecificJobConfig is now a subclass of JobsConfig, and so naturally has access to the tokenizer() method from the superclass.Code:
JavaConfigApplicationContext ctx = new JavaConfigApplicationContext(SpecificJobConfig.class);
Or, a second approach that keeps the nested class nested:Code:
@Configuration
public class JobsConfig { @Bean public DelimitedLineTokenizer tokenizer() { return new DelimitedLineTokenizer(fileDelimiter()); }
@Configuration public static class SpecificJobConfig extends ConfigurationSupport { @Bean public DelimitedLineTokenizer jobTokenizer() {DelimitedLineTokenizer tokenizer = this.getBean(DelimitedLineTokenizer.class, quot;tokenizerquot;);tokenizer.setNames(new String[]{...});return tokenizer; } }
}
Notice that the nested class now extends ConfigurationSupport? ConfigurationSupport provides getBean methods that allow subclasses to access the enclosing application context. In the scenario above, SpecificJobConfig will have its own child application context with JobsConfig being the parent context. This means that @Beans defined in SpecificJobConfig will be able to access beans defined in JobsConfig (but not the other way around).
With all that being said, the first approach is certainly the simpler of the two, and if this is all you need, I would recommend breaking out the nested class as above. The bottom line is that JavaConfig's answer to XML-style bean definition inheritance is to use traditional polymorphism.
Hope that helps!
- Chris
Wow, Chris, that was helpful :-)
Thanks a lot!
Altough first approach seems clearer and simplier, I affraid Spring Batch requires separate context for the children jobs. Anyway, I'll check and let you know.
Thank you so much for your help.
P.S. Configuration of Spring Batch with Java Config examlpe would look nice at Spring Batch documentation page, don't you think? |
|