SpEL @ConditionalOnProperty string property empty or nulll

☆樱花仙子☆ 提交于 2020-05-15 05:34:47

问题


I am currently having trouble with my dataSource bean creation on condition of String property from my applications.yaml file.

Ideally, I would only like to create the dataSource bean only if the url is set in my application.yaml file. Shouldn't create the bean if its not present (empty or null). I know this condition checks on boolean but is there anyway to check if the string property is empty or null?

DatabaseConfig.java

@Configuration
public class DatabaseConfig {
    @Value("${database.url:}")
    private String databaseUrl;

    @Value("${database.username:}")
    private String databaseUsername;

    @Value("${database.password:}")
    private String databasePassword;

    protected static final String DRIVER_CLASS_NAME = "com.sybase.jdbc4.jdbc.SybDriver";


    /**
     * Configures and returns a datasource. Optional
     *
     * @return A datasource.
     */
    @ConditionalOnProperty(value = "database.url")
    @Bean
    public DataSource dataSource() {
        return DataSourceBuilder.create()
            .url(testDatabaseUrl)
            .username(testDatabaseUsername)
            .password(testDatabasePassword)
            .build();
    }
}

application.yml (This field will be optional)

database:
  url: http://localhost:9000

回答1:


I'm having the same issue. As I undestood, you'r looking for "property exists and not empty" condition. This condition doesn't come out of the box, therefore some coding required. Solution using org.springframework.context.annotation.Conditional works for me:

  1. Create ConditionalOnPropertyNotEmpty annotation and accompanied OnPropertyNotEmptyCondition class as follows:

    // ConditionalOnPropertyNotEmpty.java
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.util.Map;
    
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Conditional(ConditionalOnPropertyNotEmpty.OnPropertyNotEmptyCondition.class)
    public @interface ConditionalOnPropertyNotEmpty {
        String value();
    
        class OnPropertyNotEmptyCondition implements Condition {
    
            @Override
            public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                Map<String, Object> attrs = metadata.getAnnotationAttributes(ConditionalOnPropertyNotEmpty.class.getName());
                String propertyName = (String) attrs.get("value");
                String val = context.getEnvironment().getProperty(propertyName);
                return val != null && !val.trim().isEmpty();
            }
        }
    }
    
  2. Annotate your bean with ConditionalOnPropertyNotEmpty, like:

    @ConditionalOnPropertyNotEmpty("database.url")
    @Bean
    public DataSource dataSource() { ... }
    

--

Alternatively, you can either set detabase.url to false explicitly (e.g. detabase.url: false) or do not define detabase.url at all in your config. Then, @ConditionalOnProperty(value = "database.url") will work for you as expected.




回答2:


You could use @ConditionalOnExpression with a Spring Expression Language (SpEL) expression as value:

@ConditionalOnExpression("!T(org.springframework.util.StringUtils).isEmpty('${database.url:}')")
@Bean
public DataSource dataSource() {
    // snip
}

For better readability and reusability you could turn this into an annotation:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnExpression("!T(org.springframework.util.StringUtils).isEmpty('${database.url:}')")
public @interface ConditionalOnDatabaseUrl {
}

@ConditionalOnDatabaseUrl
@Bean
public DataSource dataSource() {
    // snip
}



回答3:


You can try more generic purpose annotation which is standard for the Spring Core: org.springframework.context.annotation.Conditional.

In the context objects for your callback you can get all the information you need: org.springframework.context.annotation.Condition

Also you can consider using Profiles.



来源:https://stackoverflow.com/questions/46118782/spel-conditionalonproperty-string-property-empty-or-nulll

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!