No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2:
13,409
You may need to manually configure JobLauncherTestUtils
.
This looks like similar to the thread here
Spring Batch JUnit test for multiple jobs
Look into the code of JobLauncherTestUtils
, which is causing the issue.
@Autowired
public void setJob(Job job) {
this.job = job;
}
Author by
Parthiban
Updated on July 07, 2022Comments
-
Parthiban almost 2 years
I have 2 jobs running in single spring batch application based on input parameters and it is working successfully. But when i run my test case, i'm getting the below error. I'm using gradle to build my application.
No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2: pureRedDataProcessingJob,pcsMasterProcessingJob
Test class:
import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * * @author * */ @ContextConfiguration(classes = {UidBatchApplication.class, JobLauncherTestUtils.class}, initializers = ConfigFileApplicationContextInitializer.class) @RunWith(SpringJUnit4ClassRunner.class) @TestPropertySource(locations = {"classpath:application-test.properties"}) @Configuration @ActiveProfiles("test") @Profile("test") @TestConfiguration @SpringBootTest @FixMethodOrder(MethodSorters.NAME_ASCENDING) @EnableAutoConfiguration public class UidBatchApplicationTest { @Autowired public JobLauncherTestUtils jobLauncherTestUtils; @Test public void launchJob() throws Exception { JobParameters params = new JobParametersBuilder().addString("jobName", "pcsMasterProcessingJob").toJobParameters(); jobLauncherTestUtils.launchJob(params); } }
Main class configuration:
/* */ import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import javax.sql.DataSource; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; import org.springframework.batch.item.database.JdbcBatchItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.MultiResourceItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; @Configuration @ConfigurationProperties @EnableBatchProcessing public class UidApplicationConfiguration{ @Autowired private DataSource mariaDb; @Autowired private JobBuilderFactory jobBuilderFactory; @Autowired private StepBuilderFactory stepBuilderFactory; @Bean public JobExecutionListener listener() { return new JobCompletionNotificationListener(); } @Bean @Qualifier("pureRedDataProcessingJob") public Job pureRedDataProcessingJob() { return jobBuilderFactory.get(UidConstants.PURE_RED_JOB) .incrementer(new RunIdIncrementer()).listener(listener()) .flow(pureRedStep()).end().build(); } @Bean public Step pureRedStep() { return stepBuilderFactory.get("pureRedStep").<PureRedBean, PureRedBean> chunk(1) .reader(multiResourcePureRedReader()).processor(pureRedProcessor()).writer(pureRedWriter()).faultTolerant() .build(); } @Bean public MultiResourceItemReader<PureRedBean> multiResourcePureRedReader() { MultiResourceItemReader<PureRedBean> resourceItemReader = new MultiResourceItemReader<>(); resourceItemReader.setResources(getPureredFilePath()); resourceItemReader.setDelegate(pureRedReader()); return resourceItemReader; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean public FlatFileItemReader<PureRedBean> pureRedReader() { String[] namesArray = {"circularType","rotoKey","xyCoordinate","xyCoordinate","xyCoordinate","adPrintVerNum", "adStartDttm","pageNum","itemWic","upc","headLineCopy","bodyCopy","xyCoordinate","pluCode", "vendorName","xyCoordinate","xyCoordinate","xyCoordinate","imageFileName","xyCoordinate", "offerPrice","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate", "quantity","getFree","rewardSpend","rewardPoints","rewardQuantity","percentOff","offerLimit", "templateName","adPriceVerbiage","rewardVerbiage","fsiVerbiage","mirVerbiage", "ivcVerbiage","retailVerbiage","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate", "sevenPartKey","fillerThree","largeImage","xyCoordinate","xyCoordinate","xyCoordinate","xyCoordinate", "summary","additionalDealInfo","disclaimer","smallImage"}; PureredBeanWrapperFieldSetMapper beanWrapper = new PureredBeanWrapperFieldSetMapper(); beanWrapper.setTargetType(PureRedBean.class); DefaultLineMapper linemapper = new DefaultLineMapper(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(UidConstants.CSV_DELIMITER); tokenizer.setNames(namesArray); linemapper.setLineTokenizer(tokenizer ); beanWrapper.setDistanceLimit(0); linemapper.setFieldSetMapper(beanWrapper); //Create reader instance FlatFileItemReader<PureRedBean> reader = new FlatFileItemReader<>(); reader.setLineMapper(linemapper); return reader; } @Bean public ItemWriter<PureRedBean> pureRedWriter() { JdbcBatchItemWriter<PureRedBean> writer = new JdbcBatchItemWriter<>(); writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<PureRedBean>()); writer.setSql(pureredInsertQuery); writer.setDataSource(mariaDb); return writer; } @Bean public PureRedProcessor pureRedProcessor() { return new PureRedProcessor(); } @Bean @Qualifier("pcsMasterProcessingJob") public Job pcsMasterProcessingJob() { return jobBuilderFactory.get(UidConstants.PCS_MASTER_JOB) .incrementer(new RunIdIncrementer()).listener(listener()) .flow(masterStep()).end().build(); } @Bean public Step masterStep() { return stepBuilderFactory.get("masterStep").<UniqueIdMasterBean, UniqueIdMasterBean> chunk(1) .reader(multiResourceItemReader()).processor(masterProcessor()).writer(writer()).faultTolerant() .build(); } @Bean public MultiResourceItemReader<UniqueIdMasterBean> multiResourceItemReader() { MultiResourceItemReader<UniqueIdMasterBean> resourceItemReader = new MultiResourceItemReader<>(); resourceItemReader.setResources(getFilePath()); resourceItemReader.setDelegate(reader()); return resourceItemReader; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean public FlatFileItemReader<UniqueIdMasterBean> reader() { String[] namesArray = {"uniqueId","spotSeqNum","adTypeCd","adMarketCd","adStartDttm","adExpiryDttm", "adEventType","adSeqNum","adVerCd","adVerSeqNum","adPrintVerNum","adLoyaltyOfferCd","adItemCouponNum", "adItemLayoutPosNum","adItemPageNum","adItemRetailMultiple","adItemRetailPrice","adItemSingleUnitPrice", "adItemAltPriceMult","adItemAltPrice","adItemAmtOff","adItemPercentOff","adPageTypeCd","minOrderValue", "rewardType","offerValue","loyaltyPoints","targetedFlag","","categoryLevelTwo","adFillerOne", "adFillerTwo","adFillerThree","statusFlagOne","statusFlagTwo"}; BeanWrapperFieldSetMapperCustom beanWrapper = new BeanWrapperFieldSetMapperCustom(); beanWrapper.setTargetType(UniqueIdMasterBean.class); DefaultLineMapper linemapper = new DefaultLineMapper(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(UidConstants.CSV_DELIMITER); tokenizer.setNames(namesArray); linemapper.setLineTokenizer(tokenizer ); linemapper.setFieldSetMapper(beanWrapper); //Create reader instance FlatFileItemReader<UniqueIdMasterBean> reader = new FlatFileItemReader<>(); reader.setLineMapper(linemapper); return reader; } @Bean public ItemWriter<UniqueIdMasterBean> writer() { JdbcBatchItemWriter<UniqueIdMasterBean> writer = new JdbcBatchItemWriter<>(); writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<UniqueIdMasterBean>()); writer.setSql(insertQuery); writer.setDataSource(mariaDb); return writer; } @Bean public MasterProcessor masterProcessor() { return new MasterProcessor(); } @Value("${master.filePath}") private Resource[] filePath; @Value("${master.insertQuery}") private String insertQuery; @Value("${purered.filePath}") private Resource[] pureredFilePath; @Value("${purered.insertQuery}") private String pureredInsertQuery; @Value("${categoryList}") private String categoryList; private Map<String,String> categoryMap; public Resource[] getPureredFilePath() { return pureredFilePath; } public Resource[] getFilePath() { return filePath; } public void setCategoryList(String categoryList) { this.categoryList = categoryList; } /** * @return the clientTagsMap */ public Map<String, String> getCategoryMap() { if(null == categoryMap){ categoryMap = new HashMap<>(); int count = 0; String current = ""; String value = null; String key = null ; StringTokenizer tok = new StringTokenizer(categoryList, ",="); while (tok.hasMoreTokens()) { current = tok.nextToken(); // the first token in the pair is the key if (count%(PCSConstants.KEY_LENGTH)==1){ value = current; categoryMap.put(key, value); }else{ // the second is the value key = current; } count++; } } return categoryMap; } }
Could someone help me please.
-
Parthiban over 5 yearsThanks everyone. I fixed this issue by following the above steps and adding @Primary to one of my bean method.