Spring Boot #Conditional annotation gets ignored - spring

I am trying to enable scheduler based on certain properties (Condition) however it ignores my #Conditional annotation irrespective condition outcome. Any suggestions?
Conditional Class
public class SchedulerCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return property#1 || property#2
}
}
Configuration Class
#Configuration
public class Scheduler {
#Conditional(SchedulerCondition.class)
#Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
#Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public void processJobs() {
......
}
}

Related

Use #Value when defining custom #Conditional

I would like to create custom condition that will be pass as value to #Conditional interface applied on #Configuration class. Basically I would like to create beans from Config1 or Config2 depending on a configuration that is stored in a database - dbConfig.get('configType') connects to the database and returns the value. However it looks that dbConfig is not created at that time yet. What could be a way to resolve it? I would like to avoid if-else within a bean definition to differentiate creation code.
#Configuration
#Conditional(OnCondition1.class)
public class Config1{
// beans definitions
}
#Configuration
#Conditional(OnCondition2.class)
public class Config2{
// beans definitions
}
public class OnCondition1 implements Condition{
#Value("#{dbConfig.get('configType')}")
private String configType;
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return configType.equals('1');
}
}
public class OnCondition2 implements Condition{
#Value("#{dbConfig.get('configType')}")
private String configType;
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return configType.equals('2');
}
}

How to use Conditional interface in spring boot with value inside a list

I have application-sample.YAML file where I have data. After loading the data, based on certain fields. I want to decide which few components to load or not to load. I can see this below condition class loads first, as a result, I am getting the data null because this condition class is loading first before my Data loaded.
#Configuration
public class AwsCondition implements Condition {
#Autowired
MyTestData data;
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO Auto-generated method stub
log.info("inside...........condition");
if(data.getListeners().size()>1){
return true;
}
return false;
}
}
MyTestData.java
#Slf4j
#Data
#ConfigurationProperties
#Component
public class MyTestData implements InitializingBean {
List<Listener> listeners = new ArrayList<>();
#Data
public static class Listener {
private String type;
private String name;
}
#Override
public void afterPropertiesSet() throws Exception {
if (this.getListeners().isEmpty()) {
log.info("Nothing configured. Please verify application-test.yml is configured properly.");
System.exit(1);
}
}
}
ConditionTest class
#Component
#Conditional(AwsCondition.class)
public class TestS3ListenerRouter extends RouteBuilder {
//My all logic lying here
}
Try the following:
#Component
public class AwsCondition implements Condition {
#Autowired
MyTestData data;
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO Auto-generated method stub
log.info("inside...........condition");
if(data.getListeners().size()>1){
return true;
}
return false;
}
}

How to Conditionally run the Scheduled job in SpringBoot

I have scheduled job which runs incessantly after certain amount of time.
Now I want to run this scheduled job only if a condition is met. The condition is obtained at run time and it is not dependent on any configuration parameter.
How do I achieve this. I know Spring Boot 4.x provides this interface called Condition. But somehow my code doesnt work.
Here, is my code...
ScheduledTask
#Configuration
public class ScheduleTask {
#Scheduled(fixedRateString = "5000")
#Conditional(SchedulerCondition.class)
public void pollDepots() {
System.out.println("Running");
}
}
Conditional Class
public class SchedulerCondition implements Condition {
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return false;
//Here some condition needs to be implemented which is not dependent on the parameters of this method.
}
}
Await your response.
Have a lovely day.
You could pull your scheduled task in a different class:
public class ScheduledPollDepots {
#Scheduled(fixedRateString = "1000")
public void pollDepots() {
System.out.println("Running");
}
}
Then create a bean based on the conditional:
#Configuration
public class Config {
#Bean
#Conditional(SchedulerCondition.class)
public ScheduledPollDepots pollDepots() {
return new ScheduledPollDepots();
}
}
With your schedule condition as is:
public class SchedulerCondition implements Condition {
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return false;
}
}
it should work properly.

Custom Spring Condition causes java.lang.NoSuchMethodException: <init>() exception

I'm just trying to override the default behaviour of WebSecurityConfiguration and had to write my own conditions to initiate the beans based on the properties defined.
I have defined no arg constructor inside my custom condition class. Irrespective of that, I get java.lang.NoSuchMethodException, when I spin up the app.
This is how my code looks:
#Configuration
#ConditionalOnClass(WebSecurityConfigurerAdapter.class)
#Slf4j
public class WebSecurityConfiguration {
class DefaultSecurityCondition implements Condition {
public DefaultSecurityCondition(){}
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment().getProperty("property.server.authorised-clients") == null &&
context.getEnvironment().getProperty("property.server.authorised-thumbprints") == null) {
return true;
}
return false;
}
}
#Configuration
#Conditional(DefaultSecurityCondition.class)
#EnableWebSecurity
public class DefaultAuthorisationConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.and().httpBasic().disable().authorizeRequests()
.and().csrf().disable();
}
}
}
However, when I try to start my app, I get below exception.
java.lang.NoSuchMethodException:
com.test.WebSecurityConfiguration$DefaultSecurityCondition.()
What am I doing wrong?
When it’s an inner class, DefaultSecurityCondition must be declared static. When it is not static an instance cannot be created without also having an instance of its outer class.

Disable Spring Configuration if one of several profiles is present

As expected, this Configuration will not load if moduleTestis an active profile:
#Profile({"!moduleTest"})
#Configuration
public class UserConfig {
}
However, this configuration will load:
#Profile({"!moduleTest", "!featureTest"})
#Configuration
public class UserConfig {
}
Is there a way to have a Configuration that will not load if moduleTest or featureTest is active?
There is a simple (undocumented, but I think officially supported) way of doing this:
#Profile("!moduleTest & !featureTest")
By default Spring is using logical OR, this forces it to logical AND.
Try using a condition:
#Configuration
#Conditional(LoadIfNotModuleNorTestProfileCondition.class)
public class UserConfig {
}
LoadIfNotModuleNorTestProfileCondition class:
public class LoadIfNotModuleNorTestProfileCondition implements ConfigurationCondition{
#Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String[] activeProfiles = context.getEnvironment().getActiveProfiles();
for (String profile : activeProfiles) {
if(profile.equalsIgnoreCase("moduleTest") || profile.equalsIgnoreCase("featureTest")){
return false;
}
}
return true;
}
}

Resources