Spring boot properties to be loaded at initialization and respect all and control @Aspect based on the value from property file

Mani :

We are loading properties from an external file using @PropertySources. Now I want to enable/disable @Aspect based on a property. I tried using @ConditionalOnExpression which didn't work. I tried the same by creating a bean of propertyplaceholderconfig. Even in the same case, it didn't work. Then I tried @profile which also didn't work initially.

What I Figured out is that these variables are not initialized at the starting when propertysource or propertyplaceholder bean is used at startup. Some variables are always ignored like (logging.file). But @Value works fine. In order to set these variables, I've to pass them as JVM parameters.

So my questions are:
1. How can I make spring to always read specified property files at startup and respect all of them?
2. Which is the best way to enable/disable @Aspect. Using @profile or @ConditionalOnExpression or something else?

Currently, we are setting logging.file in the main method since this also behaves the same way. But you guys know that it's not the proper way as I may end up adding the properties one by one like this. I want to put all the properties into external files such that spring reads those files and sets its properties.

Our properties structure:

  1. common.properties #This has all common properties
  2. service.properties #Property specific to a service. This will also contain existing property from common.properties which will be overridden.

I understand that I can use profiles. But, we want to keep the properties outside such you need to restart service if you are changing the properties. I also don't want to pass the variables as JVM parameters then I've to pass most of the variables in this way. Passing -Dspring.config.location is also difficult as common.properties and service.properties are used and 'service.properties' filename varies for each service.

sample codes:

Mainclass:

@PropertySources({
        @PropertySource(value = "file:${property_path}/common.properties", ignoreResourceNotFound = false),
        @PropertySource(value = "file:${property_path}/service1.properties", ignoreResourceNotFound = true) })
public class MainClass {
static String logDirectory = ApplicationContext.getGlobalProperty("logging.file");

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(MainClass.class);

        Properties properties = new Properties();
        properties.put("logging.file", logDirectory);
        springApplication.setDefaultProperties(properties);
        springApplication.run(args);
    }
}

Application Context:

@Configuration
@EnableAutoConfiguration
public class ApplicationContext implements EnvironmentAware {

    private static Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        ApplicationContext.environment = environment;
    }
    public static String getGlobalProperty(String propertyName) {
    return environment.getProperty(propertyName);
    }
}

Here you can see any way I've used environment to get property. Is there any way to set the property using the environment such that while spring boot initialization itself the properties are populated?

We can also implement ApplicationContextInitializer and override initialize method to read properties. But how can I make it read 2 property files and override the duplicate property with the latest value? Reference(I'm not sure how to implement my requirements in this way.). Even in this case doesn't sound like you are trying to kill a mosquito with a hammer?

Current working Solution:

@Aspect
@Profile("!production")
@Configuration
public class ControllerAspect {
@pointcut(....)
} //Here also I've to pass spring.profiles.active as JVM params.
//setting the value in common.properties or service1.properties is not working. 

I'm a newbie to spring boot so please let me know for additional clarifications.

Mani :

It seems Spring by default loads some properties at initialization and unless until you specifically write logic to overwrite them (like the one I wrote in MainClass.java) there is no option to override those. Some of these include (logging.file, key used in @ConditionalonExpression).

Some tricks with their own challenges:

  1. Specify the properties in application.properties in your classpath. The variables loaded at the earlier stages are always read from this file. challenge: I've tight coupled all my properties into the jar and in order to change the values I've to recompile and relaunch the Jar.
  2. Use profiles and define application.properties as application-profile.properties. challenge: I've to create so many profiles and still the previous challenge exists.
  3. Pass the property value as JVM parameter as -Dproperty.key=value. challenge:seriously? How many properties am I supposed to send as JVM parameter?
  4. Implement ApplicationContextInitialize and override initialize method.challenge:Overriding Spring's default behaviour is not recommended as well as isn't it an overkill to use this just for reading property file?

Solution:

Use -Dspring.config.location to specify the property files. In this case, always spring reads the properties only from the specified location(s). You can provide multiple property files as well. Refer this for much more details. It seems if you give property locations as Directories spring loads them in reverse order. But if you specify files it follows the order specified.

Note: All these can be combined together. To know about precedence refer this.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=152552&siteId=1