How can I qualify an auto installation that I donโ€™t โ€œownโ€,

The bottom line is that the Spring Batch (v2) test framework has JobLauncherTestUtils.setJob with the @Autowired annotation. There are several Job class providers in our test suite. Since this class is not something that I can change, I'm not sure how I can qualify which task it gets automatically, which may be different for each 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 tried adding this JavaConfig that was recognized, but the error says it is still auto- 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 need a JavaConfig solution, but it would be nice. Also, I would like, if possible, to still use Autowire fields such as JobRepository, since there is only one.

+7
java spring spring-batch spring-java-config spring-3
source share
5 answers

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 last test

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

confident enough that I can just comment out my TestUtils with @Component and correctly call it and do the same.

+2
source share

My solution, when I ran into the same problem, was to restrict component checking so that only one Job bean was created in the test context.

 @Configuration @ComponentScan(basePackages={ "com.example.batch.jobs.metrics", //package where generateMetricsSnapshotJob is the only job "com.example.batch.common", "..." }) public class SpringTestConfiguration { @Bean public JobLauncherTestUtils jobLauncherTestUtils() { //generateMetricsSnapshotJob and other requirements will be autowired return new JobLauncherTestUtils(); } } 

You may need to adjust the structure of your package to work.

+2
source share

Perhaps you could use Spring profiles for this. Assign a different profile to each @Profile("profileName") definition of the bean provider (with the @Profile("profileName") annotation), and then activate the profile for the correct provider in the specific test class with the @ActiveProfiles("profileName") annotation.

0
source share
  • You can extend AutowiredAnnotationBeanPostProcessor and override the injection method.

  • Delete <context:scan .. /> entries

  • Register bean <bean class ="abCustomAutowiredAnnotationBeanPostProcessor" />

0
source share

Another type of solution is to enter it through the setter. I prefer this solution because it is clearer and simpler.

 @Configuration public class SpringTestConfiguration { @Bean public JobLauncherTestUtils jobLauncherTestUtilsForSnapshot() { return new JobLauncherTestUtils() { @Override @Autowired public void setJob(@Qualifier("generateMetricsSnapshotJob") Job job) { super.setJob(job); } }; } } 
0
source share

All Articles