Search code examples
javaspringspring-batchspring-3spring-java-config

How can I qualify an autowired setter that I don't "own"


The gist is that the Spring Batch (v2) test framework has JobLauncherTestUtils.setJob with an @Autowired annotation. Our test suite has multiple Job class providers. Since this class is not something I can modify, I'm not sure how I can qualify which job it gets autowired with, which may be different per test.

 STDOUT [WARN ] [2015.04.15 11:14:42] support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherTestUtilsForSnapshot': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.test.JobLauncherTestUtils.setJob(org.springframework.batch.core.Job); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.Job] is defined: expected single matching bean but found 2: coverageRuleBatch,generateMetricsSnapshotJob

I've tried adding this JavaConfig which is recognized, but the error says it's still autocalling setJob

@Configuration
public class SpringTestConfiguration
{
@Bean
public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot( final Job generateMetricsSnapshotJob )
{
    JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
    jobLauncherTestUtils.setJob( generateMetricsSnapshotJob );
    return jobLauncherTestUtils;
}
}

note: I don't require a JavaConfig solution, but it'd be nice. Also, I'd like, if possible, to still Autowire fields like JobRepository, as there is only one.


Solution

  • The solution I came up with

    @Configuration
    public class SpringBatchTestConfiguration
    {
    @Bean
    public static JobLauncherTestUtils jobLauncherTestUtilsForSnapshot()
    {
        return new SnapshotJobLauncherTestUtils();
    }
    
    public static class SnapshotJobLauncherTestUtils extends JobLauncherTestUtils
    {
        @Override
        @Qualifier( "generateMetricsSnapshotJob" )
        public void setJob( final Job job )
        {
            super.setJob( job );
        }
    }
    }
    

    and in the final test

    @Autowired
    @Qualifier( "jobLauncherTestUtilsForSnapshot" )
    protected JobLauncherTestUtils jobLauncherTestUtils;
    

    fairly confident I could just annotate my TestUtils with @Component and name it properly and do the same thing.