Spring Batch - MySQL to Flat File



In this chapter, we will create a Spring Batch application which uses a MySQL reader and an XML Writer.

Reader − The reader we are using in the application is JdbcCursorItemReader to read data from MySQL database.

Assume we have created a table in the MySQL database as shown below −

CREATE TABLE details.tutorialsdata( 
   tutorial_id int NOT NULL, 
   tutorial_author VARCHAR(20), 
   tutorial_title VARCHAR(20), 
   submission_date VARCHAR(20) 
);

Assume we have inserted the following records in to it.

mysql> select * from tutorialsdata; 
+-------------+-----------------+----------------+-----------------+ 
| tutorial_id | tutorial_author | tutorial_title | submission_date | 
+-------------+-----------------+----------------+-----------------+ 
|         101 | Sanjay          | Learn Java     | 06-05-2007      | 
|         102 | Abdul S         | Learn MySQL    | 19-04-2007      | 
|         103 | Krishna Kasyap  | Learn JavaFX   | 06-07-2017      | 
+-------------+-----------------+----------------+-----------------+ 
3 rows in set (0.00 sec) 

Writer − The Writer we are using in the application is FlatFileItemWriter to write the data to flatfile (.txt).

Processor − The Processor we are using in the application is a custom processor which just prints the records read from the database.

Create Project

Create a new maven project as discussed in Spring Batch - Environment Chapter.

pom.xml

Following are the content of pom.xml file used in this maven project.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tutorialspoint</groupId>
  <artifactId>SpringBatch</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringBatchExample</name>
  <properties>
      <java.version>24</java.version>
      <spring.version>7.0.0-M9</spring.version>
      <spring.batch.version>6.0.0-M3</spring.batch.version> 
      <mysql.driver.version>9.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
      <jaxb.version>4.0.4</jaxb.version>
   </properties>
   <build>      
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-core</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${spring.version}</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>${spring.version}</version>
      </dependency>
     <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency> 
      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  
      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  
      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 
      <!-- MySql Connector-->
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>
      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>
      <dependency>
         <groupId>jakarta.xml.bind</groupId>
         <artifactId>jakarta.xml.bind-api</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
      <dependency>
         <groupId>org.glassfish.jaxb</groupId>
         <artifactId>jaxb-runtime</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
   </dependencies>
</project>

jobConfig.xml

Following is the configuration file of our sample Spring Batch application. In this file, we will define the Job and the steps. In addition to these, we also define the beans for ItemReader, ItemProcessor, and ItemWriter. (Here, we associate them with their respective classes and pass the values for the required properties to configure them.)

Create this file in src > main > resources folder of maven project.

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:util = "http://www.springframework.org/schema/util" 
   xsi:schemaLocation = "http://www.springframework.org/schema/batch 
   
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <import resource = "context.xml" />  
   <bean id = "tutorial" class = "Tutorial" scope = "prototype" /> 
   <bean id = "itemProcessor" class = "com.tutorialspoint.CustomItemProcessor" />  
   
   <batch:job id = "helloWorldJob"> 
      <batch:step id = "step1"> 
         <batch:tasklet> 
            <batch:chunk reader = "mysqlItemReader" 
               writer = "flatFileItemWriter" processor = "itemProcessor" 
               commit-interval = "10"> 
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job> 
         
   <bean id = "mysqlItemReader" 
      class = "org.springframework.batch.item.database.JdbcCursorItemReader" > 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "sql" value = "select * from details.tutorialsdata" /> 
      <property name = "rowMapper">  
         <bean class = "com.tutorialspoint.TutorialRowMapper" /> 
      </property> 
   </bean>
   
   <bean id = "flatFileItemWriter" 
      class = " org.springframework.batch.item.file.FlatFileItemWriter">      
      <property name = "resource" value = "file:tutorials.txt"/> 
      <property name = "lineAggregator"> 
         <bean class = " org.springframework.batch.item.file.transform.PassThroughLineAggregator"/> 
      </property> 
   </bean> 
</beans>      

Context.xml

Following is the context.xml of our Spring Batch application. In this file, we will define the beans like job repository, job launcher, and transaction manager.

Create this file in src > main > resources folder of maven project.

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd"> 
   
   <!-- stored job-meta in database -->
   <bean id = "jobRepository" 
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
 
   <bean id = "transactionManager" 
   class = "org.springframework.batch.support.transaction.ResourcelessTransactionManager" />  
   <bean id = "jobLauncher" 
      class = "org.springframework.batch.core.launch.support.TaskExecutorJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
  
   <!-- connect to MySQL database --> 
   <bean id = "dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://localhost:3306/details" /> 
      <property name = "username" value = "guest" /> 
      <property name = "password" value = "guest123" /> 
   </bean>  
 
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql"/>   
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql"/> 
   </jdbc:initialize-database> 
</beans>   

CustomItemProcessor.java

Following is the processor class. In this class, we write the code of processing in the application. Here, we are printing the contents of each record.

Create this class in src > main > java folder of maven project.

package com.tutorialspoint;

import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  
   
   @Override 
   public Tutorial process(Tutorial item) throws Exception {  
      System.out.println("Processing..." + item); 
      return item; 
   } 
}  

TutorialRowMapper.java

Following is the TutorialRowMapper class which sets the data to the Tutorial class.

Create this class in src > main > java folder of maven project.

package com.tutorialspoint;

import java.sql.ResultSet; 
import java.sql.SQLException; 
import org.springframework.jdbc.core.RowMapper;  

public class TutorialRowMapper implements RowMapper<Tutorial> {  
   
   @Override 
   public Tutorial mapRow(ResultSet rs, int rowNum) throws SQLException {  
      
      Tutorial tutorial = new Tutorial();  
      tutorial.setTutorial_id(rs.getInt("tutorial_id")); 
      tutorial.setTutorial_author(rs.getString("tutorial_author")); 
      tutorial.setTutorial_title(rs.getString("tutorial_title")); 
      tutorial.setSubmission_date(rs.getString("submission_date"));  
      return tutorial; 
   } 
}

Tutorial.java

Following is the Tutorial class. It is a simple Java class with setter and getter methods. In this class, we are using annotations to associate the methods of this class with the tags of the XML file.

Create this class in src > main > java folder of maven project.

package com.tutorialspoint;

import jakarta.xml.bind.annotation.XmlAttribute; 
import jakarta.xml.bind.annotation.XmlElement; 
import jakarta.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "tutorial") 
public class Tutorial {  
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title;
   private String submission_date;  
 
   @XmlAttribute(name = "tutorial_id") 
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
 
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
 
   @XmlElement(name = "tutorial_author") 
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
      
   @XmlElement(name = "tutorial_title") 
   public String getTutorial_title() { 
      return tutorial_title; 
   }  
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   @XmlElement(name = "submission_date") 
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   } 
   
   @Override 
   public String toString() { 
      return "  [Tutorial id=" + tutorial_id + 
         ",Tutorial Author=" + tutorial_author  + 
         ",Tutorial Title=" + tutorial_title + 
         ",Submission Date=" + submission_date + "]"; 
   } 
}  

App.java

Following is the code which launces the batch process. In this class, we will launch the Batch Application by running the JobLauncher.

Create this class in src > main > java folder of maven project.

package com.tutorialspoint;

import org.springframework.batch.core.job.Job;
import org.springframework.batch.core.job.JobExecution;
import org.springframework.batch.core.job.parameters.JobParameters;
import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher;
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class App {  
   public static void main(String[] args) throws Exception { 
     
      String[] springConfig  =  { "jobConfig.xml" };  
      
      // Creating the application context object        
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      TaskExecutorJobLauncher jobLauncher = (TaskExecutorJobLauncher) context.getBean("jobLauncher"); 
   
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob"); 
   
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters());
      System.out.println("Exit Status : " + execution.getStatus()); 
   } 
}       

Output

Right click on the project in eclipse, select run as -> maven build . Set goals as clean package and run the project. You'll see following output.

[WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.fusesource.jansi.internal.JansiLoader in an unnamed module (file:/C:/Users/mahes/.p2/pool/plugins/org.eclipse.m2e.maven.runtime_3.9.900.20250220-2013/jars/jansi-2.4.1.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::staticFieldBase has been called by com.google.inject.internal.aop.HiddenClassDefiner (file:/C:/Users/mahes/.p2/pool/plugins/org.eclipse.m2e.maven.runtime_3.9.900.20250220-2013/jars/guice-5.1.0.jar)
WARNING: Please consider reporting this to the maintainers of class com.google.inject.internal.aop.HiddenClassDefiner
WARNING: sun.misc.Unsafe::staticFieldBase will be removed in a future release
[INFO] Scanning for projects...
[INFO] 
[INFO] [1m-------------------< [0;36mcom.tutorialspoint:SpringBatch[0;1m >-------------------[m
[INFO] [1mBuilding SpringBatchExample 0.0.1-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatch[0;1m ---[m
[INFO] Deleting C:\Users\mahes\eclipse-workspace\SpringBatch\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatch[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:3.7.0:compile[m [1m(default-compile)[m @ [36mSpringBatch[0;1m ---[m
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 6 source files to C:\Users\mahes\eclipse-workspace\SpringBatch\target\classes
[INFO] /C:/Users/mahes/eclipse-workspace/SpringBatch/src/main/java/com/tutorialspoint/App.java: C:\Users\mahes\eclipse-workspace\SpringBatch\src\main\java\com\tutorialspoint\App.java uses or overrides a deprecated API that is marked for removal.
[INFO] /C:/Users/mahes/eclipse-workspace/SpringBatch/src/main/java/com/tutorialspoint/App.java: Recompile with -Xlint:removal for details.
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatch[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:3.7.0:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatch[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.2.5:test[m [1m(default-test)[m @ [36mSpringBatch[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.4.1:jar[m [1m(default-jar)[m @ [36mSpringBatch[0;1m ---[m
[INFO] Building jar: C:\Users\mahes\eclipse-workspace\SpringBatch\target\SpringBatch-0.0.1-SNAPSHOT.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.828 s
[INFO] Finished at: 2025-09-27T16:52:48+05:30
[INFO] [1m------------------------------------------------------------------------[m

To check the output of the above SpringBatch program, right click on App.java class and select run as -> Java application. It will produce the following output −

Sept 27, 2025 4:56:18 PM org.springframework.batch.core.launch.support.TaskExecutorJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Sept 27, 2025 4:56:19 PM org.springframework.batch.core.launch.support.TaskExecutorJobLauncher run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Sept 27, 2025 4:56:19 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing...  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
Processing...  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
Processing...  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2007]
Sept 27, 2025 4:56:20 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 119ms
Sept 27, 2025 4:56:20 PM org.springframework.batch.core.launch.support.TaskExecutorJobLauncher run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 322ms
Exit Status : COMPLETED

This will generate a TXT file (tutorials.txt in root folder) with the following contents.

  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2017]
Advertisements