SpEL @ConditionalOnProperty string property empty or nulll
Solution 1
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
}
Solution 2
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:
-
Create
ConditionalOnPropertyNotEmpty
annotation and accompaniedOnPropertyNotEmptyCondition
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(); } } }
-
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.
Solution 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.
user3712237
Updated on June 26, 2022Comments
-
user3712237 almost 2 years
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
-
Hong over 2 yearsMay I know why we need generic type over there? T(org.springframework.util.StringUtils)
-
sfussenegger over 2 years@Hong the
T(..)
is to reference types and has nothing to do with generics. I assume you were thinking of<T>
. Here's the SpEL reference: docs.spring.io/spring-framework/docs/current/reference/html/…