im running a spring boot project and I'm trying to load some beans conditionaly. I have the following configuration file:
application:
components:
componentA:
- ex1
ex2
ex3
componentB:
- ex1
ex2
ex3
componentC:
- ex1
ex2
ex3
use: componentA
and the following configuration classes
@Configuration
@ConfigurationProperties(prefix = "application.components")
@Primary
@Getter
@Setter
@NoArgsConstrutor
public class MainConfig
{
private List<ComponentAConfig> componentA = new ArrayList<ComponentAConfig>();
private List<ComponentBConfig> componentB = new ArrayList<ComponentBConfig>();
private List<ComponentCConfig> componentC = new ArrayList<ComponentCConfig>();
}
@Getter
@Setter
@NoArgsConstrutor
public abstract class ComponentConfig
{
private String ex1;
private String ex2;
private String ex3;
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentA")
public class ComponentAConfig extends ComponentConfig
{
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentB")
public class ComponentBConfig extends ComponentConfig
{
}
@Configuration
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentC")
public class ComponentCConfig extends ComponentConfig
{
}
Even though I have the @ConditionalOnProperty defined on each configuration class its still loads all of them. How can I load only componentA's list and ignore the other 2? Thank you
CodePudding user response:
I guess, I would do that like this. (Edited based on later comment)
The config part class:
@Data
@NoArgsConstructor
public class ComponentConfigPart {
private String ex1;
private String ex2;
private String ex3;
}
The base class for the bean
@Data
public abstract class ComponentConfig {
private List<ComponentConfigPart> parts = new ArrayList<>();
@PostConstruct
public void init() {
System.out.println("Created instance of " this.getClass().getSimpleName());
System.out.println("Created " this);
}
}
The ComponentA class
@Component
@ConfigurationProperties(prefix = "application.components.a")
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentA")
@ToString(callSuper = true)
public class ComponentAConfig extends ComponentConfig {
}
The ComponentB class:
@Component
@ConfigurationProperties(prefix = "application.components.b")
@ConditionalOnProperty(prefix = "application", name = "use", havingValue = "componentB")
@ToString(callSuper = true)
public class ComponentBConfig extends ComponentConfig {
}
and the MainConfig, which wants to get the "selected" component:
@Configuration
public class MainConfig {
@Autowired
private ComponentConfig config;
@PostConstruct
public void init() {
System.out.println("MainConfig has autowired class of " config.getClass().getSimpleName());
}
}
Now, the properties are like this:
application:
components:
a:
parts:
- ex1: a
ex2: aa
ex3: aaa
- ex1: a2
ex2: aa2
ex3: aaa2
b:
parts:
- ex1: b
ex2: bb
ex3: bbb
- ex1: b2
ex2: bb2
ex3: bbb2
use: componentA
And results in console logs:
Created instance of ComponentAConfig
Created ComponentAConfig(super=ComponentConfig(parts=[ComponentConfigPart(ex1=a, ex2=aa, ex3=aaa), ComponentConfigPart(ex1=a2, ex2=aa2, ex3=aaa2)]))
MainConfig has autowired class of ComponentAConfig
Similarly, if the properties are like:
application:
components:
a:
parts:
- ex1: a
ex2: aa
ex3: aaa
- ex1: a2
ex2: aa2
ex3: aaa2
b:
parts:
- ex1: b
ex2: bb
ex3: bbb
- ex1: b2
ex2: bb2
ex3: bbb2
use: componentB
The result is:
Created instance of ComponentBConfig
Created ComponentBConfig(super=ComponentConfig(parts=[ComponentConfigPart(ex1=b, ex2=bb, ex3=bbb), ComponentConfigPart(ex1=b2, ex2=bb2, ex3=bbb2)]))
MainConfig has autowired class of ComponentBConfig
CodePudding user response:
That is the behavior that Im looking for, but each component is meant to be a list like this :
application:
components:
componentA:
- ex1
ex2
ex3
- ex1
ex2
ex3
componentB:
- ex1
ex2
ex3
- ex1
ex2
ex3
componentC:
- ex1
ex2
ex3
- ex1
ex2
ex3
use: componentA
Thats why I had the MainConfig class with each list.