Spring Context and Autowire configuration to copy production to test?

74 Views Asked by At

I need to write a utility that copies data from a Production to a Test environment to prepare a database for testing the application prior to a large refactoring.

I really need to re-use the existing application config files unchanged, so that I don't find myself refactoring prior to establishing a testing baseline.

My first attempt is to try to instantiate the same beans with different configuration contexts corresponding to each environment.

Here is my first attempt:

public class PrepareDatabase {

    @Component
    static class Context {
        @Autowired UserInfoSecurity userSec;
        @Autowired UserDao userDao;         
    }

    public static void main(String[] args) {
        
        try(ClassPathXmlApplicationContext prodContext =
                new ClassPathXmlApplicationContext("classpath:/prod/web-client-env.xml");    
            ClassPathXmlApplicationContext testContext =
                new ClassPathXmlApplicationContext("classpath:/test/web-client-env.xml")) {

            Context prod = prodContext.getBean(Context.class);
            Context test = testContext.getBean(Context.class);

            Stream<UserDso> users = prod.userDao.scan().map(prod.userSec::sanitize);
            test.userDao.batchPutItems(users);
        }                   
    }    
}

This fails with No qualifying bean of type '...PrepareDataba se$Context' available

I think I understand what's happening: the PrepareDatabase class is not being scanned.

But how can I fix this? I am not confident that this is even the right approach to begin with.

1

There are 1 best solutions below

0
On

Got it working by switching to AnnotationConfigApplicationContext.

The relevant section of code looks like this:

try(AnnotationConfigApplicationContext prodContext =
        new AnnotationConfigApplicationContext();

        AnnotationConfigApplicationContext testContext =
        new AnnotationConfigApplicationContext()) {

    System.setProperty("config_path", "classpath:/prod");
    prodContext.register(MyApp.class);
    prodContext.refresh();
    
    System.setProperty("config_path", "classpath:/test");
    testContext.register(MyApp.class);
    testContext.refresh();
    
    Context prod = prodContext.getBean(Context.class);
    Context test = testContext.getBean(Context.class);

YMMV - in my case the config_path variable is used in various places already to import the correct environment-specific files with something like this

<import resource="${config_path}/some_file_name.xml"/>

and this

@PropertySources({@PropertySource("${config_path}/backend.properties"),