Spring Batch Multi Reader Hibernate Writer

spring+batch+multiple+reader+hibernate+writer

Click here to download eclipse supported ZIP file



This is Main.java file having the source code to execute business logic.


 

    
package com.cv.springbatch;

import org.apache.log4j.Logger;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 @author Chandra Vardhan
 */
public class Main {

  private static final Logger LOGGER = Logger.getLogger(Main.class);

  @SuppressWarnings("resource")
  public static void main(String args[]) {

    LOGGER.info("Entered into Main.main()");

    ApplicationContext context = new ClassPathXmlApplicationContext(
        "spring-batch-context.xml");

    JobLauncher jobLauncher = (JobLaunchercontext.getBean("jobLauncher");
    Job job = (Jobcontext.getBean("resultJob");

    try {
      JobExecution execution = jobLauncher.run(job, new JobParameters());
      LOGGER.info("Job Exit Status : " + execution.getStatus());

    catch (JobExecutionException e) {
      LOGGER.info("Job ExamResult failed");
      e.printStackTrace();
    }
    LOGGER.info("Exiting from Main.main()");

  }

}

This is Result.java file having the source code to execute business logic.


 

    
package com.cv.springbatch.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Type;
import org.joda.time.LocalDate;


@Entity
@Table(name = "RESULT")
public class Result {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  
  @Column(name = "STUDENT_NAME", nullable = false)
  private String studentName;
  
  @Column(name = "DOB", nullable = false)
  @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
  private LocalDate dob;
  
  @Column(name = "PERCENTAGE", nullable = false)
  private double percentage;

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getStudentName() {
    return studentName;
  }

  public void setStudentName(String studentName) {
    this.studentName = studentName;
  }

  public LocalDate getDob() {
    return dob;
  }

  public void setDob(LocalDate dob) {
    this.dob = dob;
  }

  public double getPercentage() {
    return percentage;
  }

  public void setPercentage(double percentage) {
    this.percentage = percentage;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (id ^ (id >>> 32));
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (!(obj instanceof Result))
      return false;
    Result other = (Resultobj;
    if (id != other.id)
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "Result [id=" + id + ", studentName=" + studentName
        ", dob=" + dob + ", percentage=" + percentage + "]";
  }  

}

This is ResultFieldSetMapper.java file having the source code to execute business logic.


 

    
package com.cv.springbatch;

import org.joda.time.LocalDate;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;

import com.cv.springbatch.model.Result;

public class ResultFieldSetMapper implements FieldSetMapper<Result>{

  public Result mapFieldSet(FieldSet fieldSetthrows BindException {
    Result result = new Result();
    result.setStudentName(fieldSet.readString(0));
    result.setDob(new LocalDate(fieldSet.readDate(1,"dd/MM/yyyy")));
    result.setPercentage(fieldSet.readDouble(2));
    return result;
  }

}

This is ResultItemProcessor.java file having the source code to execute business logic.


 

    
package com.cv.springbatch;

import org.apache.log4j.Logger;
import org.springframework.batch.item.ItemProcessor;

import com.cv.springbatch.model.Result;

public class ResultItemProcessor implements ItemProcessor<Result, Result> {

  private static final Logger LOGGER = Logger.getLogger(ResultItemProcessor.class);

  public Result process(Result resultthrows Exception {
    LOGGER.info("Processing result :"+result);
    
    /*
     * Only return results which are more than 60%
     
     */
    if(result.getPercentage() 60){
      return null;
    }
    
    return result;
  }
}

This is ResultJobListener.java file having the source code to execute business logic.


 

    
package com.cv.springbatch;

import java.util.List;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;

public class ResultJobListener implements JobExecutionListener{

  private static final Logger LOGGER = Logger.getLogger(ResultJobListener.class);

  private DateTime startTime, stopTime;
  
  public void beforeJob(JobExecution jobExecution) {
    startTime = new DateTime();
    LOGGER.info("Result Job starts at :"+startTime);
  }
  

  public void afterJob(JobExecution jobExecution) {
    stopTime = new DateTime();
    LOGGER.info("Result Job stops at :"+stopTime);
    LOGGER.info("Total time take in millis :"+getTimeInMillis(startTime , stopTime));
    
    if(jobExecution.getStatus() == BatchStatus.COMPLETED){
      LOGGER.info("Result job completed successfully");
      //Here you can perform some other business logic like cleanup
    }else if(jobExecution.getStatus() == BatchStatus.FAILED){
      LOGGER.info("Result job failed with following exceptions ");
      List<Throwable> exceptionList = jobExecution.getAllFailureExceptions();
      for(Throwable th : exceptionList){
        System.err.println("exception :" +th.getLocalizedMessage());
      }
    }
  }
  
  private long getTimeInMillis(DateTime start, DateTime stop){
    return stop.getMillis() - start.getMillis();
  }
  
}



This is pom.xml file having the entries of dependency jars and information to build the application .


	
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cv.springbatch</groupId> <artifactId>SpringBatchMultiReaderHibernateWriter</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>SpringBatchMultiReaderHibernateWriter</name> <properties> <springframework.version>4.2.0.RELEASE</springframework.version> 3.0.1.RELEASE <hibernate.version>4.3.6.Final</hibernate.version> 3.18.1-GA <mysql.version>5.1.31</mysql.version> <joda-time.version>2.3</joda-time.version> 0.9.5-pre8 </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-core</artifactId> <version>${springbatch.version}</version> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-infrastructure</artifactId> <version>${springbatch.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>${javassist.version}</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda-time.version}</version> </dependency> <dependency> <groupId>org.jadira.usertype</groupId> <artifactId>usertype.core</artifactId> <version>3.0.0.CR1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> </dependencies> </project>


This is context-datasource.xml spring configuration file and these entries are used in the application.


 
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibernate" />
<property name="user" value="root" />
<property name="password" value="root" />
</bean>
</beans>

This is context-model.xml spring configuration file and these entries are used in the application.


 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"
default-autowire="byName" default-init-method="init">
<import resource="classpath:context-datasource.xml"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>com.cv.springbatch.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>

</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" />
<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

This is spring-batch-context.xml spring configuration file and these entries are used in the application.


 
<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"
xsi:schemaLocation="http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<import resource="classpath:context-model.xml"/>

<!-- JobRepository and JobLauncher are configuration/setup classes -->
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>

<bean id="multiResourceItemReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="classpath:csv/Result*.txt" />
<property name="delegate" ref="flatFileItemReader" />
</bean>
<!-- ItemReader reads a complete line one by one from input file -->
<bean id="flatFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="fieldSetMapper">
<!-- Mapper which maps each individual items in a record to properties in POJO -->
<bean class="com.cv.springbatch.ResultFieldSetMapper" />
</property>
<property name="lineTokenizer">
<!-- A tokenizer class to be used when items in input record are separated by specific characters -->
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value="|" />
</bean>
</property>
</bean>
</property>
</bean>

<!-- ItemWriter which writes data to database -->
<bean id="databaseItemWriter" class="org.springframework.batch.item.database.HibernateItemWriter">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Optional ItemProcessor to perform business logic/filtering on the input records -->
<bean id="itemProcessor" class="com.cv.springbatch.ResultItemProcessor" />
<!-- Optional JobExecutionListener to perform business logic before and after the job -->
<bean id="jobListener" class="com.cv.springbatch.ResultJobListener" />

<!-- Actual Job -->
<batch:job id="resultJob">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="multiResourceItemReader" writer="databaseItemWriter"
processor="itemProcessor" commit-interval="10" />
</batch:tasklet>
</batch:step>
<batch:listeners>
<batch:listener ref="jobListener" />
</batch:listeners>
</batch:job>
</beans>


This is log4j.properties file having the entries for logging the information into the console/file.



#By default enabling Console appender
# Root logger option
log4j.rootLogger=INFO, stdout

# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p [%c]:%L -->> %m%n

# Redirect log messages to a log file
#log4j.appender.file=org.apache.log4j.RollingFileAppender
#log4j.appender.file.File=C:\servlet-application.log
#log4j.appender.file.MaxFileSize=5MB
#log4j.appender.file.MaxBackupIndex=10
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

No comments:

Post a Comment