I have two Quartz (1.8.3) jobs, configured via Spring (2.5.6), one of them writes (send) to database, and one reads from it (check).
<bean id="scheduleFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="Check"/>
<ref bean="Send"/>
</list>
</property>
</bean>
<bean id="Send" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="StatusMonitor" />
<property name="targetMethod" value="sendMessage" />
</bean>
</property>
<property name="cronExpression" value="0 0/1 * * * ?" />
</bean>
<bean id="Check" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="StatusMonitor" />
<property name="targetMethod" value="checkAndUpdateStatus" />
</bean>
</property>
<property name="cronExpression" value="30 0/1 * * * ?" />
</bean>
Transaction manager is set up:
<tx:annotation-driven transaction-manager="TransactionManager"/>
In both jobs I explicitly run read/write operations in transactions like this:
#Override
public synchronized void sendMessage() {
try {
TransactionTemplate tt = new TransactionTemplate(ptm);
tt.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
...
statusDAO.update(status);
...
}
});
log.info("Status was updated");
} catch (Exception e) {
...
}
}
where ptm is a TransactionManager bean, injected via Spring.
I see "Status was updated" record in logs, but when I read this record from transactional read method it is outdated sometimes. Moreover, when I use an SQL editor to read this record it is outdated too.
I don't understand, why transactions dont work in this case, do you have any ideas?
Thanks.
For anyone that might be interested. This worked for me
<bean name="applicationDataCollectorControllerJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="org.mypckage.controller.jobs.ApplicationDataCollectorController" />
<property name="jobDataAsMap">
<map>
<!--<entry key="timeout" value="1" />-->
<entry key="genericService" value-ref="genericService" />
<entry key="applicationDataCollectorService" value-ref="applicationDataCollectorService" />
<entry key="transactionManager" value-ref="transactionManager" />
</map>
</property>
</bean>
--- in the scheduler bean---
#Override
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
getApplicationDataCollectorService().collectData(transactionManager);
}
----In the applicationDataCollectorService bean-----
public void collectData( org.springframework.transaction.jta.JtaTransactionManager transactionManager) {
try {
this.transactionManager = transactionManager;
testTransactionalSave();
} catch (Exception e) {
BUSY = false;
e.printStackTrace();
}
}
}
private void testTransactionalSave() throws Exception {
TransactionTemplate tt = new TransactionTemplate(transactionManager);
tt.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus ts) {
try {
ApplicationParameter appPara = null;
List<ApplicationParameter> appParaList = genericService.getListFromHQL("select o from ApplicationParameter as o order by o.id desc", false);
if (appParaList != null) {
if (appParaList.size() > 0) {
appPara = (ApplicationParameter) appParaList.get(0);
appPara.setLastBankStatementMailNum(appPara.getLastBankStatementMailNum() + 10);
appPara = (ApplicationParameter) genericService.mergeObject(appPara);
System.out.println(" num is now = " + appPara.getLastBankStatementMailNum());
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
Note: dont forget to declare transactionManager as private properties in both beans with public setter and getter for spring to wire it up. Any Questions? yemiosigbesan#gmail.com
Related
This is the bean code for cron scheduler. declaration for runMeTask And runMeJob
<bean id="runMeTask" class="com.ascent.fieldomobify.cornScheduler.RunMeTask"/>
<bean name="runMeJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.ascent.fieldomobify.cornScheduler.RunMeJob" />
<property name="jobDataAsMap">
<map>
<entry key="runMeTask" value-ref="runMeTask" />
</map>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runMeJob"/>
<property name="cronExpression" value="0 0 13 * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
it get call directly from bean scheduler configuration
The first class is RunMeJob
public class RunMeJob extends QuartzJobBean {
private RunMeTask runMeTask;
public void setRunMeTask(RunMeTask runMeTask) {
this.runMeTask = runMeTask;
}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
try {
runMeTask.printMe();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
form here i call the controller's method which is having the logic
Second class RunMeTask
public class RunMeTask{
#Autowired
WorkOrderController workorderContoller;
public void setWorkorderContoller(WorkOrderController workorderContoller) {
this.workorderContoller = workorderContoller;
}
public void printMe() throws ParseException {
workorderContoller.printSysOut();
}
}
there are some scenarios where you can get that behavior, please check this thread: Java Spring #Scheduled tasks executing twice
I have two transaction managers defined in my context file as follows
<tx:annotation-driven transaction-manager="firstTransactionManager" />
<bean id="secondDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="---" />
<property name="url" value="datasource1" />
<property name="username" value="----" />
<property name="password" value="----" />
</bean>
<bean id="firstTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="firstDataSource" />
<qualifier value="firstTxManager"/>
</bean>
<bean id="secondTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="secondDataSource" />
<qualifier value="secondTxManager"/>
</bean>
<bean id="firstDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="---" />
<property name="url" value="datasource2" />
<property name="username" value="---" />
<property name="password" value="---" />
</bean>
And I my class definitions are as follows
#Transactional("firstTransactionManager")
public class JdbcMain {
#Autowired
private static DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public static void main(String args[]){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
TransactionExample example = (TransactionExample) ctx.getBean("transExample");
example.create();
}
}
And my example class is as follows:
#Transactional("secondTransactionManager")
public void create(DataSource dataSource2) {
try {
this.jdbcTemplate = new JdbcTemplate(dataSource2);
String sql = "insert into testtable values (?,?)";
getJdbcTemplate().update(sql,1,"1244343");
String marksSql="insert into testtable values (?,?)";
int i=2/0; //added to depict roll back behaviour of the transaction when exception occurs
getJdbcTemplate().update(marksSql,2,"sujay");
System.out.println("transaction committed");
} catch (RuntimeException e) {
throw e;
}
}
But the second transaction manager doesn't seem to work and the transaction is not rolled back (The first insert is executed). Can you provide me an idea.
On production environment I got following error.
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot create PoolableConnectionFactory (The Network Adapter could not establish the connection)
When I connect through toad, it said ORA-12541 no listener error. The issue resolved after restart of linstener.
But the actual issue may be that lot of connections opened by the web application and it is not closing that. Following are my code and configuration.
I am using EcllipseLink, dbcp2 for connections
<persistence-unit name="persistance-unit" transaction-type="RESOURCE_LOCAL">
<class>com.company.model.Characteristic</class>
...
<!--more classes -->
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.weaving" value="false"/>
</properties>
</persistence-unit>
dbcp2 settings
<bean id="datasource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxIdle" value="10" />
<property name="maxTotal" value="200" />
<property name="maxWaitMillis" value="60000" />
<property name="validationQuery" value="select 1 from dual" />
<property name="validationQueryTimeout" value="10" />
<property name="testOnBorrow" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<property name="minEvictableIdleTimeMillis" value="60000" />
<property name="numTestsPerEvictionRun" value="5" />
<property name="defaultAutoCommit" value="true" />
</bean>
Connection Factory
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistance-unit"/>
<property name="dataSource" ref="datasource"/>
<property name="jpaVendorAdapter">
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="database" value="ORACLE"/>
</bean>
</property>
</bean>
Transaction Management
Abstract GenericDao
public abstract class GenericDao<T> implements IGenericDao<T> {
#PersistenceContext
protected EntityManager entityManager
private Class<T> type
public GenericDao() {
Type t = getClass().getGenericSuperclass()
ParameterizedType pt = (ParameterizedType) t
type = (Class) pt.getActualTypeArguments()[0]
}
#Override
public T save(final T t) {
this.entityManager.persist(t)
return t
}
public def saveObj(def t) {
try {
this.entityManager.persist(t)
}catch(e){
log.info("Error occured: ", e)
}
return t
}
#Override
public void delete(final Object id) {
this.entityManager.remove(this.entityManager.getReference(type, id))
}
#Override
public T find(final Object id) {
return (T) this.entityManager.find(type, id)
}
#Override
public T update(final T t) {
return this.entityManager.merge(t)
}
#Override
public def executeNamedQuery(String namedQueryName, Map<String, Object> queryParams)
{
List results = null
try {
Query query = entityManager.createNamedQuery(namedQueryName)
if (queryParams) {
addPrametersToQuery(query, queryParams)
}
results = query.getResultList()
} catch (NoResultException e) {
} catch (Exception e) {
log.error("Error occured: ", e)
throw e
}
return results
}
}
Dao component using that Generic Dao
#Component("characteristicDao")
class CharacteristicDao extends GenericDao<Characteristic> implements ICharacteristicDao {
public def getCharacteristics(String name){
log.info("Entering getCharacteristics")
Characteristic characteristic = (PrmCharacteristic) executeQueryWithSingleResult("select b from Characteristic b where b.name=:name", [name:name])
log.info("Exiting getCharacteristics")
return characteristic
}
}
I use CharacteristicDao component to interact with database. Similarly I have other dao also. I have just given one example.
I use #Transactional in service for the transaction. Any master can help me please what I am doing wrong.
I am calling the sendMessage function from Main method and it gives Null Pointer Exception while creating the object Queue (this.queue).
Main method:
public void start()
{
AuthorisationServiceImpl authorisationServiceImpl = new AuthorisationServiceImpl();
try {
authorisationServiceImpl.fromMain();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Starting Client Application");
AbstractApplicationContext context = new FileSystemXmlApplicationContext("resources/applicationContext.xml");
System.out.println("Spring context loaded.");
context.registerShutdownHook();
System.out.println("ShutdownHook registered.");
MainTestClient mainTestClient = new MainTestClient();
mainTestClient.start();
}
And the method that i am calling in another class is
public class AuthorisationServiceImpl {
#Autowired
private MessageSender messageSender;
private MessageReceiver messageReceiver;
private JmsTemplate jmsTemplate;
private Queue queue;
public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public Queue getQueue() {
return queue;
}
public void setQueue(Queue queue) {
this.queue = queue;
}
public MessageReceiver getMessageReceiver() {
return messageReceiver;
}
public void setMessageReceiver(MessageReceiver messageReceiver) {
this.messageReceiver = messageReceiver;
}
private ConfigProperties configProperties;
public void fromMain() throws InterruptedException {
System.out.println("Init method called");
String message = "AAA-MM-CCC";
long count = new Long("000001").longValue();
while (true)
{
//container.start();
StringBuffer corelationId = new StringBuffer();
if (count == 1000000) {
count = new Long("000001").longValue();
}
corelationId.append(message);
corelationId.append(String.format("%6s", String.valueOf(count)).replace(' ', '0'));
byte[] myvar = "Message".getBytes();
System.out.println("Writing message having correlationId: " + corelationId.toString() + " to the queue.");
sendMessage(corelationId.toString(),myvar);
count++;
Thread.sleep(5000);
}
}
/*public boolean sendMessage(String correlationId) throws ServiceException {
byte[] myvar = "Message".getBytes();
boolean response = false;
try {
MessageSender messageSenderVar = new MessageSender();
System.out.println("Writing message having correlationId: " + correlationId + " to the queue.");
// writing message to the request queue.
sendMessage(correlationId,myvar);
//messageReceiver.getMessage();
}catch(Exception e) {
throw new ServiceException("Exception:",e);
}
return response;
}
*/
public void sendMessage(final String correlationId, final byte[] bytes) {
this.jmsTemplate.send(this.queue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
BytesMessage bytesMessage = session.createBytesMessage();
bytesMessage.setJMSCorrelationID(configProperties.getPREFIX_VALUE() + correlationId);
// message will follow expiration time as configured in properties
bytesMessage.writeBytes(bytes);
return bytesMessage;
}
});
System.out.println("Message " + configProperties.getPREFIX_VALUE() + correlationId + " with correlation id: " + configProperties.getPREFIX_VALUE() + correlationId + " written to the queue.");
}
public MessageSender getMessageSender() {
return messageSender;
}
public void setMessageSender(MessageSender messageSender) {
this.messageSender = messageSender;
}
public ConfigProperties getConfigProperties() {
return configProperties;
}
public void setConfigProperties(ConfigProperties configProperties) {
this.configProperties = configProperties;
}
}
I am getting Null Pointer Exception while calling sendMessage Method. Is there any problem in calling the non static methods from Static Method?
Starting Client Application
Nov 23, 2015 12:49:53 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext#5ba28182: startup date [Mon Nov 23 12:49:53 UTC 2015]; root of context hierarchy
Nov 23, 2015 12:49:53 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from file [/app/dev-data/node1/support/tactical_tools/gwatest/client1/resources/applicationContext.xml]
Nov 23, 2015 12:49:54 PM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from URL [file:resources/config.properties]
Nov 23, 2015 12:49:54 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#6b915330: defining beans [propertyConfigurer,configProperties,jndiTemplate,connectionFactory,paymentRequestQueue,paymentResponseQueue,jmsTemplate,messageSender,authorisationResponseHandler,authorisationServiceImpl,jmsContainer]; root of factory hierarchy
Nov 23, 2015 12:49:55 PM org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup start
INFO: Starting beans in phase 2147483647
Spring context loaded.
ShutdownHook registered.
Init method called
Writing message having correlationId: AAA-MM-CCC000001 to the queue.
Exception in thread "main" java.lang.NullPointerException
at aero.sita.uatp.client.AuthorisationServiceImpl.sendMessage(AuthorisationServiceImpl.java:114)
at aero.sita.uatp.client.AuthorisationServiceImpl.fromMain(AuthorisationServiceImpl.java:86)
at aero.sita.uatp.client.MainTestClient.start(MainTestClient.java:15)
at aero.sita.uatp.client.MainTestClient.main(MainTestClient.java:31)
When i call the sendMessage Normally without Main Method then i am able to connect successfully. And i am using the Spring ApplicationContext to initialize queues as below
<!-- Config property -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:resources/config.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="order" value="0" />
</bean>
<!-- App config properties -->
<bean id="configProperties" class="aero.sita.uatp.server.utilities.ConfigProperties">
<property name="properties">
<props>
<prop key="prefix.correlation">${prefix.correlation}</prop>
</props>
</property>
</bean>
<!-- jndi Template -->
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${broker.initialContexFactory}</prop>
<prop key="java.naming.provider.url">${broker.provide.url}</prop>
</props>
</property>
</bean>
<!-- JMS Connection factory -->
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${broker.connectionFactory}</value>
</property>
</bean>
<!-- Auth (Payment) Request queue -->
<bean id="paymentRequestQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${payment.request}</value>
</property>
</bean>
<!-- Auth (Payment) Response queue -->
<bean id="paymentResponseQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${payment.response}</value>
</property>
</bean>
<!-- JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="timeToLive" value="${payment.request.expiration}" />
<property name="receiveTimeout" value="${payment.response.receive.timeout}" />
</bean>
<bean id="messageSender" class="aero.sita.uatp.server.MessageSender">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="queue" ref="paymentResponseQueue" />
<property name="configProperties" ref="configProperties" />
</bean>
<bean id="authorisationServiceImpl" class="aero.sita.uatp.server.AuthorisationServiceImpl">
<property name="messageSender" ref="messageSender" />
<property name="configProperties" ref="configProperties" />
</bean>
<bean id="authorisationResponseHandler" class="aero.sita.uatp.server.AuthorisationResponseHandler">
<property name="configProperties" ref="configProperties" />
<property name="messageSender" ref="messageSender" />
</bean>
<!-- and this is the message listener container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
<property name="autoStartup" value="TRUE" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="paymentRequestQueue" />
<property name="messageListener" ref="authorisationResponseHandler" />
</bean>
You are getting a NullPointerException when trying to invoke this.jmsTemplate.send(...) method, because your jmsTemplate variable is NULL, or never initialized. One more thing is that you are not using the spring bean authorisationServiceImpl, but you are instantiating the class manually.
First you need to set the jmsTemplate in your bean:
<bean id="authorisationServiceImpl" class="aero.sita.uatp.server.AuthorisationServiceImpl">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="messageSender" ref="messageSender" />
<property name="configProperties" ref="configProperties" />
</bean>
Second you should not instantiate the class:
AuthorisationServiceImpl authorisationServiceImpl = new AuthorisationServiceImpl();
try {
authorisationServiceImpl.fromMain();
}
But get it from application context, that you have just created
AuthorisationServiceImpl authorisationServiceImpl = context.getBean("authorisationServiceImpl", AuthorisationServiceImpl.class );
I am looking for a guidance/solution with Spring batch integration. I have a directory to which external application will send xml files. My application should read the file content and move the file to another directory.
The application should be able to process the files in parallel.
Thanks in advance.
You can use Spring Integration ftp / sftp combined with Spring Batch:
1.Spring Integration Ftp Configuration :
<bean id="ftpClientFactory"
class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${host.name}" />
<property name="port" value="${host.port}" />
<property name="username" value="${host.username}" />
<property name="password" value="${host.password}" />
<property name="bufferSize" value="100000"/>
</bean>
<int:channel id="ftpChannel" />
<int-ftp:outbound-channel-adapter id="ftpOutbound"
channel="ftpChannel" remote-directory="/yourremotedirectory/" session-factory="ftpClientFactory" use-temporary-file-name="false" />
2.Create your reader and autowire a service to provide your items if needed :
#Scope("step")
public class MajorItemReader implements InitializingBean{
private List<YourItem> yourItems= null;
#Autowired
private MyService provider;
public YourItem read() {
if ((yourItems!= null) && (yourItems.size() != 0)) {
return yourItems.remove(0);
}
return null;
}
//Reading Items from Service
private void reloadItems() {
this.yourItems= new ArrayList<YourItem>();
// use the service to provide your Items
if (yourItems.isEmpty()) {
yourItems= null;
}
}
public MyService getProvider() {
return provider;
}
public void setProvider(MyService provider) {
this.provider = provider;
}
#Override
public void afterPropertiesSet() throws Exception {
reloadItems();
}
}
3. Create Your Own Item Processor
public class MyProcessor implements
ItemProcessor<YourItem, YourItem> {
#Override
public YourItem process(YourItem arg0) throws Exception {
// Apply any logic to your Item before transferring it to the writer
return arg0;
}
}
4. Create Your Own Writer :
public class MyWriter{
#Autowired
#Qualifier("ftpChannel")
private MessageChannel messageChannel;
public void write(YourItem pack) throws IOException {
//create your file and from your Item
File file = new File("the_created_file");
// Sending the file via Spring Integration Ftp Channel
Message<File> message = MessageBuilder.withPayload(file).build();
messageChannel.send(message);
}
5.Batch Configuration :
<bean id="dataSourcee"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSourcee" />
<property name="transactionManager" ref="transactionManagerrr" />
<property name="databaseType" value="" />
</bean>
<bean id="transactionManagerrr"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
6.Another ApplicationContext file to Configure Your Job :
<context:annotation-config />
<bean id="provider" class="mypackage.MyService" />
<context:component-scan base-package="mypackage" />
<bean id="myReader" class="mypackage.MyReader"
<property name="provider" ref="provider" />
</bean>
<bean id="myWriter" class="mypackage.MyWriter" />
<bean id="myProcessor" class="mypackage.MyProcessor" />
<bean id="mReader"
class="org.springframework.batch.item.adapter.ItemReaderAdapter">
<property name="targetObject" ref="myReader" />
<property name="targetMethod" value="read" />
</bean>
<bean id="mProcessor"
class="org.springframework.batch.item.adapter.ItemProcessorAdapter">
<property name="targetObject" ref="myProcessor" />
<property name="targetMethod" value="process" />
</bean>
<bean id="mWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter">
<property name="targetObject" ref="myWriter" />
<property name="targetMethod" value="write" />
</bean>
<batch:job id="myJob">
<batch:step id="step01">
<batch:tasklet>
<batch:chunk reader="mReader" writer="mWriter"
processor="mProcessor" commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myRunScheduler" class="mypackage.MyJobLauncher" />
<task:scheduled-tasks>
<task:scheduled ref="myJobLauncher" method="run"
cron="0 0/5 * * * ?" />
<!-- this will maker the job runs every 5 minutes -->
</task:scheduled-tasks>
7.Finally Configure A launcher to launch your job :
public class MyJobLauncher {
#Autowired
private JobLauncher jobLauncher;
#Autowired
#Qualifier("myJob")
private Job job;
public void run() {
try {
String dateParam = new Date().toString();
JobParameters param = new JobParametersBuilder().addString("date",
dateParam).toJobParameters();
JobExecution execution = jobLauncher.run(job, param);
execution.stop();
} catch (Exception e) {
e.printStackTrace();
}
}