What's the properties file equivalent property for the #Profile(!dev) annotation? - spring

In Spring-boot you can use the #Profile(!dev) annotation to exclude beans and classes from being provided when certain profiles are active or not active. Is there an equivalent property for this that can be used inside the application.yml?

You can use #ConditionalOnProperty.
#Bean
#ConditionalOnProperty(name = "stage", havingValue = "prod")
public NotificationSender notificationSender2() {
return new SmsNotification();
}
Which will be disabled if you have stage=dev in your application properties.
There's blog from Eugen on it: https://www.baeldung.com/spring-conditionalonproperty

Why not use profile seperators in configuration file?
---
spring:
profiles: dev
my-app.some-property: ...
---
spring:
profiles: uat
my-app.some-property: ...
Or like GeertPt said in, you can use org.springframework.boot.autoconfigure.condition.ConditionalOnProperty annotation to deal with your bean creation.
Even if you want you profile to be dev, you can use a feature flag to enable a bean. This might be helpful where you have to maintain multiple profiles.
For instance, I needed to log few properties on my stag server, but I was not willing to change in code base. So, with below, I only need to change the config-repo file and set the flag accordingly.
my-app-dev.yml
my-app:
cloud:
config:
log-details: true
log-ssl-properties: true
swagger:
enabled: false
ConditionalConfigurationPropertiesLogger.java
#Slf4j
#Component
#Profile({"native", "dev"})
#ConditionalOnProperty(name = "my-app.cloud.config.log-details", havingValue = "true")
public class ConditionalConfigurationPropertiesLogger implements CommandLineRunner {
#Override
public void run(String... args) {
log.info(" <details> ");
}
}
}

Related

Custom AutoConfiguration is not detected by spring application

Hi I created one custom auto configuration library as following:
#Configuration
#EnableConfigurationProperties(RefreshProperties.class)
public class PropertiesRefresherAutoConfiguration {
public static final String AUTO_REFRESH_ENABLED = RefreshProperties.PROPERTIES_AUTO_REFRESH + ".enabled";
#ConditionalOnProperty(
name = PropertiesRefresherAutoConfiguration.AUTO_REFRESH_ENABLED,
havingValue = "true"
)
#Bean
public Refresher getRefresher(){
return new Refresher();
}
}
I have added spring.factories in META-INF with content:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.bla.PropertiesRefresherAutoConfiguration
What I want to achieve is when I use dependency of this custom library and I set application.yaml properties:
properties:
refresh:
enabled: true
Refresher instance should automatically be created. In Refresher class there is one method that should be called on application start
#PostConstruct
public void startTask() {
//do something
}
In my main application I've added dependency to it and defined properties in application.yaml but Refresher Bean is not created and startTask() method is not called
I have tried to remove #Conditional annotation in order to create instance of Refresh every time, but that didn't help.

Spring boot: how to read specific property from application.yml and ignore others

My goal is to read some property from application.yml file and ignore other properties. This is need for testing purposes - I want to read part of config and validate it. I want to ignore other properties because Spring Boot tring to handle it but this is no need for my test.
Example.
Config:
first:
property:
{cipher}value #for example Spring trying to handle cipher and throws exception
second:
property:
value
Class (using String for simplification):
#Configuration
public class Configuration {
#Bean
#ConfigurationProperties(prefix = "second.property")
public String secondProperty() {
return new String();
}
}
Test class:
#SpringBootTest
public class ConfigPropertiesCheckerIntegrationTest {
#Autowired
String secondProperty;
#Test
void checkAutoConfigEndpointProperties() {
assertThat(secondProperty, is(notNullValue()));
}
}
So question: how to ignore first.property and say Spring just skip it?
You can disable {cipher}ed properties decryption with spring.cloud.decrypt-environment-post-processor.enabled=false. E.g:
#SpringBootTest(properties = "spring.cloud.decrypt-environment-post-processor.enabled=false")

Spring ShedLock without Database

I want to disable ShedLock with a configuration yml property. So i don't have to create the table shedlock, if it is not necessary. Is there a way to disable Shedlock usage?
I tried to remove #Bean lockProvider but then I got this message:
No qualifying bean of type 'net.javacrumbs.shedlock.core.LockProvider
If you are using ShedLock in combination with the shedlock-spring dependency, there probably is a #EnableSchedulerLock somewhere in your application. Move the LockProvider bean setup together with the annotation to a separate #Configuration class and add a #ConditionalOnProperty annotation, for example:
#Configuration
#EnableSchedulerLock
#ConditionalOnProperty(value = "shedlock.enabled", matchIfMissing = true)
public class ShedLockConfig {
#Bean
public LockProvider lockProvider(DataSource dataSource) {
// ...
}
}
And add the property
shedlock:
enabled: true
To your application.yml

#PropertySource does not bind a String propety to enum automatically?

In our integration test using springboot 1.4, we used
#ConfigurationProperties(locations = "classpath:test.yml")
with the locations attribute. This was mapping a string property to enum automatically. But starting from springboot 1.5, the locations attribute is removed.
As a workaround, I'm using #PropertySource but this doesn't support yaml file. So, I'm using a factory class to convert the yaml to java.util.properites. But I'm facing issues, with string property not binding to enum automatically.
Is there any good solution for this?
You can map yaml file to config class
The relative path of application.yml file is /myApplication/src/main/resources/application.yml.
The Spring application takes the first profile as the default profile unless declared otherwise in the Spring application.
YAML FILE
spring:
profiles: test
name: test-YAML
environment: test
servers:
- www.abc.test.com
- www.xyz.test.com
---
spring:
profiles: prod
name: prod-YAML
environment: production
servers:
- www.abc.com
- www.xyz.com
Binding YAML to a Config Class
To load a set of related properties from a properties file, we will create a bean class:
Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class YAMLConfig {
private String name;
private String environment;
private List<String> servers = new ArrayList<>();
// standard getters and setters
}
The annotation used here are:
#Configuration marks the class as a source of bean definitions
#ConfigurationProperties binds and validates the external configurations to a configuration class
#EnableConfigurationProperties this annotation is used to enable #ConfigurationProperties annotated beans in the Spring application
USAGE:
#SpringBootApplication
public class MyApplication implements CommandLineRunner {
 
    #Autowired
    private YAMLConfig myConfig;
 
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApplication.class);
        app.run();
    }
 
    public void run(String... args) throws Exception {
        System.out.println("using environment: " + myConfig.getEnvironment());
        System.out.println("name: " + myConfig.getName());
        System.out.println("servers: " + myConfig.getServers());
    }
}

Hibernate Envers with Spring Boot - configuration

I'm trying to setup Hibernate Envers to work with my Spring Boot application.
I've included the Envers dependency and added #Audited annotations and it works fine, but I'm unable to configure specific Envers properties, Spring Boot doesn't seem to pick them up.
Specifically, I've tried to set the different db schema for audit tables by putting these to application.properties, but without luck:
hibernate.envers.default_schema=app_audit
or
org.hibernate.envers.default_schema=app_audit
or
spring.jpa.hibernate.envers.default_schema=app_audit
Neither of these work. Does anyone know how to set these?
EDIT.
As M. Deinum suggested I tried:
spring.jpa.properties.org.hibernate.envers.default_schema=app_audit
and it worked!
For all those configuration settings that aren't by default available you can specify them by simply prefixing them with spring.jpa.properties. Those properties will be added, as is, to the EntityManagerFactory (as JPA Properties).
spring.jpa.properties.org.hibernate.envers.default_schema=app_audit
Adding the above to the application.properties will add the properties and should configure Hibernate Envers.
This is also documented in the Spring Boot reference guide.
Links
Configure JPA properties
Envers Properties
Looking through the HibernateJpaAutoConfiguration class I can't see any support for envers properties. The following might not be the best solution but nevertheless your can give it a try.
In order to have Spring Boot support the envers properties you have to:
override the current AutoConfiguration class that Spring Boot uses to configure the Hibernate properties, so it will read the envers properties from your property files.
This will read the spring.jpa.hibernate.envers.default_schema from your file and add it to the properties of the entityManagerFactoryBean:
#Configuration
public class HibernateEnversAutoConfiguration extends HibernateJpaAutoConfiguration {
private RelaxedPropertyResolver environment;
public HibernateEnversAutoConfiguration() {
this.environment = null;
}
#Override
public void setEnvironment(Environment environment) {
super.setEnvironment(environment);
this.environment = new RelaxedPropertyResolver(environment, "spring.jpa.hibernate.");
}
#Override
protected void configure(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
super.configure(entityManagerFactoryBean);
Map<String, Object> properties = entityManagerFactoryBean.getJpaPropertyMap();
properties.put("hibernate.envers.default_schema", this.environment.getProperty("envers.default_schema"));
}
}
exclude the original HibernateJpaAutoConfiguration that Spring Boot uses and add your own as a bean so it will be replaced:
#EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)
#EnableJpaRepositories(basePackages = "com.gabrielruiu.test")
#EntityScan(basePackages = "com.gabrielruiu.test")
#ComponentScan(basePackages = "com.gabrielruiu.test")
#Configuration
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
#Bean
public HibernateEnversAutoConfiguration hibernateEnversAutoConfiguration() {
return new HibernateEnversAutoConfiguration();
}
}
For those using MySQL and Spring Boot, the suggestion of using:
spring.jpa.properties.org.hibernate.envers.default_schema=yourAuditSchema will not work.
Use this instead:
spring.jpa.properties.org.hibernate.envers.default_catalog=yourAuditSchema
I use with yaml format:
spring:
jpa:
properties:
org:
hibernate:
format_sql: false
envers:
audit_table_suffix: AUDIT
revision_field_name: NRO_ID_REVISAO_AUDITORIA
revision_type_field_name: TPO_REVISAO_AUDITORIA

Resources