I need to make a customized reader by extending JdbcCursorItemReader. I am doing it as below:
package sample.peektry;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("myReader")
public class MyReader implements ItemReader<MyBean> {
@Autowired
MyPeekableReader myPeekableReader;
public MyPeekableReader getMyPeekableReader() {
return myPeekableReader;
}
public void setMyPeekableReader(MyPeekableReader myPeekableReader) {
this.myPeekableReader = myPeekableReader;
}
@Override
public MyBean read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
System.out.println(" I will peek and read... :)");
return null;
}
}
package sample.peektry;
import org.springframework.batch.item.support.SingleItemPeekableItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("myPeekableReader")
public class MyPeekableReader extends SingleItemPeekableItemReader<MyBean> {
@Autowired
private MyJdbcReader myJdbcReader;
public MyJdbcReader getMyJdbcReader() {
return myJdbcReader;
}
public void setMyJdbcReader(MyJdbcReader myJdbcReader) {
this.myJdbcReader = myJdbcReader;
}
}
Further, MyRowMapper implements RowMapper
and has @Component("myRowMapper")
. Similarly, MyPrepStmntSetter implements PreparedStatementSetter
and has @Component("myPrepStmntSetter")
package sample.peektry;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("myJdbcReader")
public class MyJdbcReader extends JdbcCursorItemReader<MyBean> {
@Resource
DataSource dataSource;
@Autowired
MyRowMapper myRowMapper;
@Autowired
MyPrepSetter myPrepSetter;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public MyRowMapper getMyRowMapper() {
return myRowMapper;
}
public void setMyRowMapper(MyRowMapper myRowMapper) {
this.myRowMapper = myRowMapper;
}
public MyPrepSetter getMyPrepSetter() {
return myPrepSetter;
}
public void setMyPrepSetter(MyPrepSetter myPrepSetter) {
this.myPrepSetter = myPrepSetter;
}
}
Configurations:
in batch-infra.xml:
<batch:job-repository id="jobRepository" data-source="dataSource"
transaction-manager="transactionManager" />
<!-- connect to database -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/MyDB" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"></property>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
batch-jobs.xml:
<import resource="classpath:/META-INF/spring/batch/jobs/myJob.xml" />
in app-context.xml(after xmlns and all):
<context:component-scan base-package="sample.peektry" />
<import resource="classpath:/META-INF/spring/batch/batch-infra.xml" />
<import resource="classpath:/META-INF/spring/batch/batch-jobs.xml" />
The above configuration is working fine for all the properties except dataSource. I.e. on running, I am getting: IllegalArgumentException DataSource must be provided
Stacktrace:
2014-02-16 14:56:07,195 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c7e553: startup date [Sun Feb 16 14:56:07 IST 2014]; root of context hierarchy>
2014-02-16 14:56:07,291 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/app-context.xml]>
2014-02-16 14:56:07,625 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/batch/batch-infra.xml]>
2014-02-16 14:56:10,210 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/batch/batch-jobs.xml]>
2014-02-16 14:56:12,766 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [META-INF/spring/batch/jobs/myJob.xml]>
2014-02-16 14:56:12,872 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'myJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]>
2014-02-16 14:56:13,115 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d332b: defining beans [myJdbcReader,myPeekableReader,myPrepSetter,myReader,myRowMapper,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,jobRepository,dataSource,jobLauncher,transactionManager,step1,myJob]; root of factory hierarchy>
2014-02-16 14:56:13,215 INFO [org.springframework.jdbc.datasource.DriverManagerDataSource] - <Loaded JDBC driver: org.apache.derby.jdbc.ClientDriver>
2014-02-16 14:56:13,304 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d332b: defining beans [myJdbcReader,myPeekableReader,myPrepSetter,myReader,myRowMapper,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,jobRepository,dataSource,jobLauncher,transactionManager,step1,myJob]; root of factory hierarchy>
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myJdbcReader' defined in file [C:\Users\user\Documents\workspace-sts-3.3.0.RELEASE\sb-listener-test\target\classes\sample\peektry\MyJdbcReader.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: DataSource must be provided
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at sample.peektry.MyMain.main(MyMain.java:16)
Caused by: java.lang.IllegalArgumentException: DataSource must be provided
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.batch.item.database.AbstractCursorItemReader.afterPropertiesSet(AbstractCursorItemReader.java:150)
at org.springframework.batch.item.database.JdbcCursorItemReader.afterPropertiesSet(JdbcCursorItemReader.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 12 more
Where I am getting wrong? Is it due to mixing XML configuration and component scan?