Skip to content
Advertisement

Spring Batch Wildcard ItemWriter

I have one dummy question. To explain my use-case, I have different type of DAOs; say Users, Beers… etc. I wanted to use one generic ItemWriter for all of them. I created a CommonComponentConfiguration where I defined;

@Bean
@Qualifier(WRITER_INSERT_TO_DATABASE_BEAN)
public ItemWriter<?> insertDbItemWriter(@Qualifier(DATA_SOURCE) DataSource dataSource,
                                        @Qualifier("insertSql") String insertSql) {
         return new MyItemWriter<>(dataSource, insertSql);
     }

The writer class goes like this;

@Slf4j
public class MyItemWriter<T> extends JdbcBatchItemWriter<T> {

    public MyItemWriter(DataSource dataSource, String sql) {
        this.setDataSource(dataSource);
        this.setSql(sql);
        this.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        this.setAssertUpdates(false);
    }

    @Override
    public void write(List<? extends T> items) {
        try {
            super.write(items);
        } catch (Exception e) {
            log.error("Could not write the items " + items);
            log.error(e.getMessage());
        }
    }
}

So far everything is okay. Where things gets complicated is, I have seperate configuration classes for each repository where I define repository specific items. For instance the step for inserting to DB for Users.

@Bean
@Qualifier(STEP_INSERT_TO_DB_BEAN)
public Step insertToDbStep(@Qualifier(READER_LOADED_INPUT_DATA_BEAN) ListItemReader<User> sourceItemReader, UserInsertProcessor userInsertProcessor, @Qualifier(WRITER_INSERT_TO_DATABASE_BEAN)
        ItemWriter<User> dbItemWriter) {
    return stepBuilderFactory.get("processInsertStep").<User, User>chunk(100)
            .reader(sourceItemReader)
            .processor(userInsertProcessor)
            .writer(dbItemWriter)
            .build();
}

When I write this code in IJ is complaining Could not autowire. Qualified bean must be of 'ItemWriter<User>' type. , but heavens sake when I execute the code, it works, and does what its supposed to do. When I debug, it binds the right thing.

Well, you may say, if it works don’t touch it. However I really want to know what’s happening behind the curtains.

Also, if you see a flaw in the design (such as trying to use one common thing for everything), your suggestions are more than welcomed.

Thank you in advance.

PS: Seen this thread below, looks like very similar -if not the same- case. However I would like to know if there’s something to do with the generics here. IntelliJ IDEA shows errors when using Spring’s @Autowired annotation

Edit: Error

Advertisement

Answer

However I really want to know what’s happening behind the curtains.

For this IntelliJ IDEA warning, you are right that it is the same issue discussed in IntelliJ IDEA shows errors when using Spring’s @Autowired annotation (and also as explained by Eugene in comments)

Also, if you see a flaw in the design (such as trying to use one common thing for everything), your suggestions are more than welcomed.

If the current approach works for you, you can use it. However, I would recommend making one thing do one thing and do it well. In your case, this would be using an item writer for each domain type and wrap those writers in a ClassifierCompositeItemWriter. The composite writer uses a Classifier to classify items and call the corresponding writer accordingly.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement