<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sheila&#039;s Blog &#187; spring batch</title>
	<atom:link href="http://sheilapollard.com/tag/spring-batch/feed/" rel="self" type="application/rss+xml" />
	<link>http://sheilapollard.com</link>
	<description>Software Development</description>
	<lastBuildDate>Wed, 24 Mar 2010 17:19:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Configure Spring Batch to persist to a database</title>
		<link>http://sheilapollard.com/2010/03/24/configure-spring-batch-to-persist-to-a-database/?utm_campaign=feed&utm_medium=feed&utm_source=blog</link>
		<comments>http://sheilapollard.com/2010/03/24/configure-spring-batch-to-persist-to-a-database/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 17:15:21 +0000</pubDate>
		<dc:creator>Sheila</dc:creator>
				<category><![CDATA[spring]]></category>
		<category><![CDATA[seam]]></category>
		<category><![CDATA[spring batch]]></category>

		<guid isPermaLink="false">http://sheilapollard.com/?p=534</guid>
		<description><![CDATA[For anything more than a simplistic application, you will probably want to persist the spring batch job data to a data source.  Spring batch uses a set of database tables to store information about the jobs being executed.  You will need to create the following tables in your database (this script will work [...]]]></description>
			<content:encoded><![CDATA[<p>For anything more than a simplistic application, you will probably want to persist the spring batch job data to a data source.  Spring batch uses a set of database tables to store information about the jobs being executed.  You will need to create the following tables in your database (this script will work for oracle).
<code>CREATE TABLE BATCH_JOB_INSTANCE  (
  JOB_INSTANCE_ID NUMBER(19,0)  NOT NULL PRIMARY KEY ,  
  VERSION NUMBER(19,0) ,  
  JOB_NAME VARCHAR2(100) NOT NULL, 
  JOB_KEY VARCHAR2(32) NOT NULL,
  constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ;

CREATE TABLE BATCH_JOB_EXECUTION  (
  JOB_EXECUTION_ID NUMBER(19,0)  NOT NULL PRIMARY KEY ,
  VERSION NUMBER(19,0)  ,  
  JOB_INSTANCE_ID NUMBER(19,0) NOT NULL,
  CREATE_TIME TIMESTAMP NOT NULL,
  START_TIME TIMESTAMP DEFAULT NULL , 
  END_TIME TIMESTAMP DEFAULT NULL ,
  STATUS VARCHAR2(10) ,
  EXIT_CODE VARCHAR2(20) ,
  EXIT_MESSAGE VARCHAR2(2500) ,
  LAST_UPDATED TIMESTAMP,
  constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
  references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
  
CREATE TABLE BATCH_JOB_PARAMS  (
  JOB_INSTANCE_ID NUMBER(19,0) NOT NULL ,
  TYPE_CD VARCHAR2(6) NOT NULL ,
  KEY_NAME VARCHAR2(100) NOT NULL , 
  STRING_VAL VARCHAR2(250) , 
  DATE_VAL TIMESTAMP DEFAULT NULL ,
  LONG_VAL NUMBER(19,0) ,
  DOUBLE_VAL NUMBER ,
  constraint JOB_INST_PARAMS_FK foreign key (JOB_INSTANCE_ID)
  references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
  
CREATE TABLE BATCH_STEP_EXECUTION  (
  STEP_EXECUTION_ID NUMBER(19,0)  NOT NULL PRIMARY KEY ,
  VERSION NUMBER(19,0) NOT NULL,  
  STEP_NAME VARCHAR2(100) NOT NULL,
  JOB_EXECUTION_ID NUMBER(19,0) NOT NULL,
  START_TIME TIMESTAMP NOT NULL , 
  END_TIME TIMESTAMP DEFAULT NULL ,  
  STATUS VARCHAR2(10) ,
  COMMIT_COUNT NUMBER(19,0) , 
  READ_COUNT NUMBER(19,0) ,
  FILTER_COUNT NUMBER(19,0) ,
  WRITE_COUNT NUMBER(19,0) ,
  READ_SKIP_COUNT NUMBER(19,0) ,
  WRITE_SKIP_COUNT NUMBER(19,0) ,
  PROCESS_SKIP_COUNT NUMBER(19,0) ,
  ROLLBACK_COUNT NUMBER(19,0) , 
  EXIT_CODE VARCHAR2(20) ,
  EXIT_MESSAGE VARCHAR2(2500) ,
  LAST_UPDATED TIMESTAMP,
  constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT  (
  STEP_EXECUTION_ID NUMBER(19,0) NOT NULL PRIMARY KEY,
  SHORT_CONTEXT VARCHAR2(2500) NOT NULL,
  SERIALIZED_CONTEXT CLOB , 
  constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
  references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;

CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
  JOB_EXECUTION_ID NUMBER(19,0) NOT NULL PRIMARY KEY,
  SHORT_CONTEXT VARCHAR2(2500) NOT NULL,
  SERIALIZED_CONTEXT CLOB , 
  constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ MAXVALUE 9223372036854775807 NOCYCLE;
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ MAXVALUE 9223372036854775807 NOCYCLE;
CREATE SEQUENCE BATCH_JOB_SEQ MAXVALUE 9223372036854775807 NOCYCLE;</code></p>
<p>You need to add the following jar files to your ear file:</p>
<blockquote><p>
org.springframework.jdbc-3.0.0.RELEASE.jar<br />
com.springsource.com.thoughtworks.xstream-1.3.0.jar<br />
com.springsource.org.codehaus.jettison-1.0.0.jar<br />
commons-dbcp-1.2.2.jar
</p></blockquote>
<p>You first configure your jobRepository
<code>&lt;bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"&gt;
    &lt;property name="dataSource" ref="dataSource"/&gt;
      &lt;property name="transactionManager" ref="transactionManager"/&gt;
&lt;/bean&gt;</code></p>
<p>You then need to configure your datasource and transaction manager.  For oracle the following configuration worked:
<code>&lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
      &lt;property name="dataSource" ref="dataSource"/&gt;
  &lt;/bean&gt;

  &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"&gt;
    &lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /&gt;
    &lt;property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" /&gt;
    &lt;property name="username" value="username" /&gt;
    &lt;property name="password" value="password" /&gt;
  &lt;/bean&gt;</code></p>
<p>Now you will see entries persisted to the database for each new job that is run.</p>
<br /><a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3NoZWlsYXBvbGxhcmQuY29tLz9wPTUzNCNjb21tZW50cw==" title=\"Comments on &quot;Configure Spring Batch to persist to a database&quot;\"><img src="http://sheilapollard.com/wp-content/plugins/feed-comments-number/image.php?534" alt="Comments" /></a> <img src="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?view=1&post_id=534" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://sheilapollard.com/2010/03/24/configure-spring-batch-to-persist-to-a-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuring Seam and Spring Batch</title>
		<link>http://sheilapollard.com/2010/02/04/configuring-seam-and-spring-batch/?utm_campaign=feed&utm_medium=feed&utm_source=blog</link>
		<comments>http://sheilapollard.com/2010/02/04/configuring-seam-and-spring-batch/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 11:26:41 +0000</pubDate>
		<dc:creator>Sheila</dc:creator>
				<category><![CDATA[seam]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring batch]]></category>

		<guid isPermaLink="false">http://sheilapollard.com/?p=529</guid>
		<description><![CDATA[Seam provides jbpm for handling workflows, but doesn&#8217;t have anything dedicated so far to the issue of batch processing.  While jbpm will handle complex business conditional steps, some steps are repetitive rather than complex and are better suited to a batch framework, like Spring Batch.  In order to use Spring Batch with Seam, [...]]]></description>
			<content:encoded><![CDATA[<p>Seam provides jbpm for handling workflows, but doesn&#8217;t have anything dedicated so far to the issue of batch processing.  While jbpm will handle complex business conditional steps, some steps are repetitive rather than complex and are better suited to a batch framework, like Spring Batch.  In order to use Spring Batch with Seam, you will first need to follow the steps to configure Seam to start up the Spring container and make the required Spring beans accessible as Seam components.</p>
<p>These steps describe adding a very simplistic batch job and calling it from a Seam class.  As a simple batch example, the database tables usually used by Spring batch will be held in memory and not persisted to a database.</p>
<p>The first step in the batch process is to upload a csv file and extract the list of people contained in it.  The test file is:
<code>title,firstname,surname,dateOfBirth,country
Mr,John,Smith,1949,United States
Ms,Jane,Smith,03/09/1994,England
Mr,David,Moore,13/04/1972,France
Mr,Robert,Fisher,26/06/1946,Brazil</code></p>
<p>You need to add the following jar files to your ear file (in addition to the ones here.</p>
<blockquote><p>
spring/org.springframework.batch.core-2.0.0.RELEASE.jar<br />
spring/org.springframework.batch.infrastructure-2.0.0.RELEASE.jar<br />
spring/aopalliance-1.0.jar<br />
spring/org.springframework.aop-3.0.0.RELEASE.jar<br />
spring/org.springframework.jdbc-3.0.0.RELEASE.jar<br />
spring/org.springframework.transaction-3.0.0.RELEASE.jar
</p></blockquote>
<p>You should create a new folder to hold the configuration files for your batch jobs on the class path, eg. WEB-INF/classes/exampleJob.xml.  You can import these files into your applicationContext.xml.
<code>&lt;import resource="classpath:/jobs/exampleJob.xml" /&gt;</code></p>
<p>Rather than persisting information about the batch job to a database, you can define an in-memory data source to hold the information in applicationContext.xml.  You need a job repository and a transaction manager defined.
<code>&lt;bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"&gt;
      &lt;property name="transactionManager" ref="transactionManager"/&gt;
  &lt;/bean&gt;

  &lt;bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/&gt;</code></p>
<p>The exampleJob.xml contains the configuration for the batch job itself:
<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:seam="http://jboss.com/products/seam/spring-seam"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:batch="http://www.springframework.org/schema/batch"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://jboss.com/products/seam/spring-seam http://jboss.com/products/seam/spring-seam-2.2.xsd
    http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd"&gt;

  &lt;bean id="exampleJob"
    class="com.example.ExampleJob"&gt;
    &lt;seam:component/&gt;
  &lt;/bean&gt;
  
  &lt;bean id="jobLauncher"
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher"&gt;
    &lt;property name="jobRepository" ref="jobRepository" /&gt;
    &lt;seam:component/&gt;
  &lt;/bean&gt;
  
  &lt;batch:job id="personUpload"&gt;
    &lt;batch:step id="personload"&gt;
      &lt;batch:tasklet&gt;
        &lt;batch:chunk reader="personItemReader" writer="exampleWriter" commit-interval="5"/&gt;
      &lt;/batch:tasklet&gt;
    &lt;/batch:step&gt;
  &lt;/batch:job&gt;

  &lt;bean id="personItemReader" class="org.springframework.batch.item.file.FlatFileItemReader"&gt;
    &lt;property name="resource" value="file://C:/workspaces/test/v3_crime/testdata/watchlist/uploadwatchlist1.csv" /&gt;
    &lt;property name="lineMapper"&gt;
      &lt;bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper"&gt;
        &lt;property name="lineTokenizer"&gt;
          &lt;bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"&gt;
            &lt;property name="names" value="title,firstname,surname,dateOfBirth,country" /&gt;
          &lt;/bean&gt;
        &lt;/property&gt;  
        &lt;property name="fieldSetMapper"&gt;
          &lt;bean class="com.example.ExampleFieldSetMapper" /&gt;
        &lt;/property&gt;
      &lt;/bean&gt;
    &lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;bean id="exampleWriter" class="com.example.ExampleWriter" /&gt;
  
&lt;/beans&gt;</code><br />
In this file we define the exampleJob bean which is a java class called ExampleJob.  This is a spring class that is wrapped as a seam component.  We also define a job launcher that uses the job repository already defined in applicationContext.xml.  </p>
<p>The batch job called personUpload contains the step personload which defines a reader and writer for the data.  To read the csv file we use Spring Batch&#8217;s FlatFileItemReader and tell it the names of the fields that are contained in the file.  It uses the ExampleFieldSetMapper class to do the mapping.  We also define an exampleWriter bean that will be used to display the data uploaded in the logs.</p>
<p>The ExampleJob.java class simply launches the batch job.
<code>public class ExampleJob {

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job job;

    public void launchJob() throws Exception {
        jobLauncher.run(job, new JobParameters());
    }
}</code></p>
<p>The ExampleFieldSetMapper.java takes the data read in from each line in the csv file and stores it as an UploadedPerson (a simple class containing the properties and getters/setters required).
<code>public class ExampleFieldSetMapper implements FieldSetMapper&lt;UploadedPerson&gt; {

    public UploadedPerson mapFieldSet(FieldSet fs) {
        if(fs == null){
            return null;
        }
        
        UploadedPerson person = new UploadedPerson();
        person.setTitle(fs.readString("title"));
        person.setFirstname(fs.readString("firstname"));
        person.setSurname(fs.readString("surname"));
        person.setDateOfBirth(fs.readString("dateOfBirth"));
        person.setCountry(fs.readString("country"));
        return person;
    }

}</code></p>
<p>ExampleWriter.java just logs the list of UploadedPerson objects to the log files:
<code>public class ExampleWriter implements ItemWriter&lt;Object&gt; {

    UploadWatchlistService  watchlistService;
    
    private static final Log log = LogFactory.getLog(ExampleWriter.class);
    
    /**
     * @see ItemWriter#write(Object)
     */
    public void write(List&lt;? extends Object&gt; data) throws Exception {
        log.info(data);
    }

}</code></p>
<p>Now in the seam component that calls the job we inject the ExampleJob and
<code>@In(create=true)
private ExampleJob exampleJob;
...
try {
  exampleJob.launchJob();
} catch (Exception e) {
  log.info("There was an error: " + e);
}</code></p>
<br /><a href="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?url=aHR0cDovL3NoZWlsYXBvbGxhcmQuY29tLz9wPTUyOSNjb21tZW50cw==" title=\"Comments on &quot;Configuring Seam and Spring Batch&quot;\"><img src="http://sheilapollard.com/wp-content/plugins/feed-comments-number/image.php?529" alt="Comments" /></a> <img src="http://sheilapollard.com/wp-content/plugins/feed-statistics.php?view=1&post_id=529" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://sheilapollard.com/2010/02/04/configuring-seam-and-spring-batch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
