'No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2:
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.
Solution 1:[1]
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;
}
Solution 2:[2]
I had the same problem, and solved it by adding the following:
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Legna |
