Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best practice for handling multiple profiles in Spring with java config?

Tags:

java

spring

On a project I'm currently working on we have the need for multiple profiles, i.e. "default" and "test". To solve this, we've implemented a main context class, ApplicationContext.java, with 2 public static inner classes: one of them defines the default profile, the other defines the test profile. Our web.xml is set to target ApplicationContext.java.

Code as follows:

@Configuration
//import common beans
public class ApplicationContext {

  @Configuration  
  @Profile("default")
  public static class DefaultContext {
    //default beans
  }  

  @Configuration
  @Profile("test")
  public static class TestContext {
    //test beans
  }

}

My problem with this is that the main context class, ApplicationContext.java, is in the production environment (i.e. src/main/java) with references to files in the test environment. If there is a better way to define these profiles without introducing this dependency from production code to test code, that would of course be preferable.

We`ve tested these cases with a jetty instance in a test class, started from a main method. This instance is run with the following command:

System.setProperty("spring.profiles.active", "test");
like image 581
Jarle Svendsrud Avatar asked Apr 09 '13 13:04

Jarle Svendsrud


1 Answers

If all the beans are common between your profiles (that is, both DefaultContext and TestContext contains the same bean definitions), define an interface for the dependencies, e.g:

public interface SystemConfiguration {

    public DataSource getDataSource();
    public SomeService getService();

}

Then implement each profile with this interface:

@Profile("production")
@Configuration
public class ProductionConfiguration implements SystemConfiguration {
    public DataSource getDataSource() {
         // create and return production datasource
    }

    public SomeService getService() {
        // Create and return production service
    }
}

And then do the same for test.

@Profile("test")
@Configuration
public class TestConfiguration implements SystemConfiguration {
    public DataSource getDataSource() {
         // create and return dummy datasource
    }

    public SomeService getService() {
        // Create and return dummy service
    }
}

Then you can inject this into your main configuration:

@Configuration
public class ApplicationContext {
    @Autowired
    private SystemConfiguration systemConfiguration;

}
like image 183
NilsH Avatar answered Nov 15 '22 13:11

NilsH