countryroadscat
countryroadscat

Reputation: 1750

Externalize properties and logback Spring

I'm using Spring (without spring-boot). I want to build standalone application that can be run with default configuration (logback.xml and application.properties in resource folder) or with -Dconfig.folder=/path/to/custom/external/directory (logback.xml and application.properties in /path/to/custom/external/directory). When application will be run with -Dconfig.folder param AppConfig should load both logback and properties from external directory.

Is there anyway to make external folder act like a resource folder?

If not, what is a common solution for this?

My current implementation (using default resource folder only):

App.java

public class App {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        SampleAction p = context.getBean(SampleAction.class);
        p.performTask();
    }
}

AppConfig.java

@ComponentScan
@PropertySource("classpath:application.properties")
class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

SampleAction.java

@Component
public class SampleAction {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${sample.prop}")
    private String sampleProp;

    public void performTask(){
        logger.debug(sampleProp);
    }
}

logback.xml and application.properties are not relevant to the problem

Upvotes: 0

Views: 1837

Answers (2)

Abhijit Sarkar
Abhijit Sarkar

Reputation: 24583

Unlike the other answer suggests, if you use file prefix in @PropertySource, you're screwed because it won't be able to load the default application.properties from the jar. What you should do is the following:

@PropertySource("${config.folder:'classpath:'}/application.properties")
public class AppConfig

For logback.xml:

@Value("${config.folder}:")
private String configFolder;

InputStream = Optional.of(new ClassPathResource(configFolder + "/logback.xml"))
    .filter(r -> r.exists())
    .orElse(new ClassPathResource("classpath:/logback.xml"))
    .getInputStream();

In both cases, I gave preference to the command line argument over the default packaged files. Of course, I didn't compile the above, so there may be typos or minor errors, but you get the idea.

Edit:

Since OP claims to not understand where to run the above code -

public class AppConfig {
    @PostConstruct
    void init() {
        // init logback here
    }
}

Upvotes: 1

Amit K Bist
Amit K Bist

Reputation: 6818

For log4j.xml

-Dlog4j.configuration=C:\neon\log4j.xml as VM argument

In main() method:

String filename = System.getProperty("log4j.configuration");
DOMConfigurator.configure(filename);

For external properties file:

-Dext.prop.dir=C:\neon as VM argument

Change in your AppConfig class will be like

@PropertySource("file:///${ext.prop.dir}/application.properties")
public class AppConfig{
}

Run App class with VM arguments as below and both file will be use from external location

-Dlog4j.configuration=C:\neon\log4j.xml -Dext.prop.dir=C:\neon

Upvotes: 0

Related Questions