IN PROGRESS - issue BATCH-412: consistent ItemStream key prefixes
http://jira.springframework.org/browse/BATCH-412 added ExecutionContextUserSupport class as superclass for those who need to save data into ExecutionContext - removes the tons of copy-pastes used to handle naming and unique key generation
This commit is contained in:
@@ -24,12 +24,11 @@ import org.hibernate.SessionFactory;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.reader.AbstractItemStreamItemReader;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -50,13 +49,11 @@ import org.springframework.util.StringUtils;
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class HibernateCursorItemReader extends AbstractItemStreamItemReader implements Skippable, InitializingBean {
|
||||
public class HibernateCursorItemReader extends ExecutionContextUserSupport implements ItemReader, ItemStream, Skippable, InitializingBean {
|
||||
|
||||
private static final String RESTART_DATA_ROW_NUMBER_KEY = ClassUtils.getShortName(HibernateCursorItemReader.class)
|
||||
+ ".rowNumber";
|
||||
private static final String RESTART_DATA_ROW_NUMBER_KEY = "rowNumber";
|
||||
|
||||
private static final String SKIPPED_ROWS = ClassUtils.getShortName(HibernateCursorItemReader.class)
|
||||
+ ".skippedRows";
|
||||
private static final String SKIPPED_ROWS = "skippedRows";
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@@ -81,9 +78,12 @@ public class HibernateCursorItemReader extends AbstractItemStreamItemReader impl
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private String name = HibernateCursorItemReader.class.getName();
|
||||
|
||||
private boolean saveState = false;
|
||||
|
||||
|
||||
public HibernateCursorItemReader() {
|
||||
setName(HibernateCursorItemReader.class.getSimpleName());
|
||||
}
|
||||
|
||||
public Object read() {
|
||||
if (!initialized) {
|
||||
@@ -235,10 +235,6 @@ public class HibernateCursorItemReader extends AbstractItemStreamItemReader impl
|
||||
cursor.setRowNumber(lastCommitRowNumber - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(String key){
|
||||
return name + "." + key;
|
||||
}
|
||||
|
||||
public void setSaveState(boolean saveState) {
|
||||
this.saveState = saveState;
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.exception.ResetFailedException;
|
||||
@@ -102,17 +103,17 @@ import org.springframework.util.StringUtils;
|
||||
* @author Lucas Ward
|
||||
* @author Peter Zozom
|
||||
*/
|
||||
public class JdbcCursorItemReader implements ItemReader, InitializingBean, ItemStream, Skippable {
|
||||
public class JdbcCursorItemReader extends ExecutionContextUserSupport implements ItemReader, InitializingBean, ItemStream, Skippable {
|
||||
|
||||
private static Log log = LogFactory.getLog(JdbcCursorItemReader.class);
|
||||
|
||||
public static final int VALUE_NOT_SET = -1;
|
||||
|
||||
private static final String CURRENT_PROCESSED_ROW = "sqlCursorInput.lastProcessedRowNum";
|
||||
private static final String CURRENT_PROCESSED_ROW = "lastProcessedRowNum";
|
||||
|
||||
private static final String SKIPPED_ROWS = "sqlCursorInput.skippedRows";
|
||||
private static final String SKIPPED_ROWS = "skippedRows";
|
||||
|
||||
private static final String SKIP_COUNT = "sqlCursorInput.skippedRrecordCount";
|
||||
private static final String SKIP_COUNT = "skippedRrecordCount";
|
||||
|
||||
private Connection con;
|
||||
|
||||
@@ -150,8 +151,10 @@ public class JdbcCursorItemReader implements ItemReader, InitializingBean, ItemS
|
||||
private boolean initialized = false;
|
||||
|
||||
private boolean saveState = false;
|
||||
|
||||
private String name = JdbcCursorItemReader.class.getName();
|
||||
|
||||
public JdbcCursorItemReader() {
|
||||
setName(JdbcCursorItemReader.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that mandatory properties are set.
|
||||
@@ -381,9 +384,9 @@ public class JdbcCursorItemReader implements ItemReader, InitializingBean, ItemS
|
||||
if (saveState) {
|
||||
Assert.notNull(executionContext, "ExecutionContext must not be null");
|
||||
String skipped = skippedRows.toString();
|
||||
executionContext.putString(addName(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1));
|
||||
executionContext.putLong(addName(CURRENT_PROCESSED_ROW), currentProcessedRow);
|
||||
executionContext.putLong(addName(SKIP_COUNT), skipCount);
|
||||
executionContext.putString(getKey(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1));
|
||||
executionContext.putLong(getKey(CURRENT_PROCESSED_ROW), currentProcessedRow);
|
||||
executionContext.putLong(getKey(SKIP_COUNT), skipCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,23 +402,23 @@ public class JdbcCursorItemReader implements ItemReader, InitializingBean, ItemS
|
||||
initialized = true;
|
||||
|
||||
// Properties restartProperties = data.getProperties();
|
||||
if (!context.containsKey(addName(CURRENT_PROCESSED_ROW))) {
|
||||
if (!context.containsKey(getKey(CURRENT_PROCESSED_ROW))) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.currentProcessedRow = context.getLong(addName(CURRENT_PROCESSED_ROW));
|
||||
this.currentProcessedRow = context.getLong(getKey(CURRENT_PROCESSED_ROW));
|
||||
rs.absolute((int) currentProcessedRow);
|
||||
}
|
||||
catch (SQLException se) {
|
||||
throw getExceptionTranslator().translate("Attempted to move ResultSet to last committed row", sql, se);
|
||||
}
|
||||
|
||||
if (!context.containsKey(addName(SKIPPED_ROWS))) {
|
||||
if (!context.containsKey(getKey(SKIPPED_ROWS))) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] skipped = StringUtils.commaDelimitedListToStringArray(context.getString(addName(SKIPPED_ROWS)));
|
||||
String[] skipped = StringUtils.commaDelimitedListToStringArray(context.getString(getKey(SKIPPED_ROWS)));
|
||||
for (int i = 0; i < skipped.length; i++) {
|
||||
this.skippedRows.add(new Long(skipped[i]));
|
||||
}
|
||||
@@ -510,14 +513,6 @@ public class JdbcCursorItemReader implements ItemReader, InitializingBean, ItemS
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String addName(String key) {
|
||||
return name + "." + key;
|
||||
}
|
||||
|
||||
public void setSaveState(boolean saveState) {
|
||||
this.saveState = saveState;
|
||||
}
|
||||
|
||||
@@ -5,48 +5,52 @@ import java.util.List;
|
||||
import org.springframework.batch.io.driving.DrivingQueryItemReader;
|
||||
import org.springframework.batch.io.driving.KeyGenerator;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.orm.ibatis.SqlMapClientTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.ibatis.sqlmap.client.SqlMapClient;
|
||||
|
||||
/**
|
||||
* {@link KeyGenerator} based on iBATIS ORM framework. It is functionally similar to
|
||||
* {@link SingleColumnJdbcKeyGenerator} but does not make assumptions about the primary key
|
||||
* structure.
|
||||
*
|
||||
* {@link KeyGenerator} based on iBATIS ORM framework. It is functionally
|
||||
* similar to {@link SingleColumnJdbcKeyGenerator} but does not make assumptions
|
||||
* about the primary key structure.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
* @author Lucas Ward
|
||||
* @see DrivingQueryItemReader
|
||||
*/
|
||||
public class IbatisKeyGenerator implements KeyGenerator {
|
||||
public class IbatisKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator {
|
||||
|
||||
public static final String RESTART_KEY = "IbatisDrivingQueryItemReader.keyIndex";
|
||||
public static final String RESTART_KEY = "keyIndex";
|
||||
|
||||
private SqlMapClientTemplate sqlMapClientTemplate;
|
||||
|
||||
private String drivingQuery;
|
||||
|
||||
private String restartQueryId;
|
||||
|
||||
private String name = IbatisKeyGenerator.class.getName();
|
||||
|
||||
public IbatisKeyGenerator() {
|
||||
setName(IbatisKeyGenerator.class.getSimpleName());
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the keys using the provided driving query id.
|
||||
*
|
||||
*
|
||||
* @see org.springframework.batch.io.support.AbstractDrivingQueryItemReader#retrieveKeys()
|
||||
*/
|
||||
public List retrieveKeys(ExecutionContext executionContext) {
|
||||
if(executionContext.containsKey(getKey(RESTART_KEY))){
|
||||
if (executionContext.containsKey(getKey(RESTART_KEY))) {
|
||||
Object key = executionContext.getString(getKey(RESTART_KEY));
|
||||
return sqlMapClientTemplate.queryForList(restartQueryId, key);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return sqlMapClientTemplate.queryForList(drivingQuery);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object)
|
||||
*/
|
||||
public void saveState(Object key, ExecutionContext executionContext) {
|
||||
@@ -55,7 +59,8 @@ public class IbatisKeyGenerator implements KeyGenerator {
|
||||
executionContext.putString(getKey(RESTART_KEY), key.toString());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -81,7 +86,7 @@ public class IbatisKeyGenerator implements KeyGenerator {
|
||||
|
||||
/**
|
||||
* Set the id of the restart query.
|
||||
*
|
||||
*
|
||||
* @param restartQueryId id of the iBatis select statement that will be used
|
||||
* to retrieve the list of primary keys after a restart.
|
||||
*/
|
||||
@@ -90,14 +95,7 @@ public class IbatisKeyGenerator implements KeyGenerator {
|
||||
}
|
||||
|
||||
public final SqlMapClientTemplate getSqlMapClientTemplate() {
|
||||
return sqlMapClientTemplate;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String getKey(String key){
|
||||
return name + "." + key;
|
||||
return sqlMapClientTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,25 +20,26 @@ import java.util.List;
|
||||
import org.springframework.batch.io.driving.DrivingQueryItemReader;
|
||||
import org.springframework.batch.io.driving.KeyGenerator;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>Jdbc implementation of the {@link KeyGenerator} interface that works for composite keys.
|
||||
* (i.e. keys represented by multiple columns) A sql query to be used to return the keys and
|
||||
* a {@link ExecutionContextRowMapper} to map each row in the resultset to an Object must be set in
|
||||
* order to work correctly.
|
||||
* <p>
|
||||
* Jdbc implementation of the {@link KeyGenerator} interface that works for
|
||||
* composite keys. (i.e. keys represented by multiple columns) A sql query to be
|
||||
* used to return the keys and a {@link ExecutionContextRowMapper} to map each
|
||||
* row in the resultset to an Object must be set in order to work correctly.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @see DrivingQueryItemReader
|
||||
* @since 1.0
|
||||
*/
|
||||
public class MultipleColumnJdbcKeyGenerator implements
|
||||
KeyGenerator {
|
||||
public class MultipleColumnJdbcKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator {
|
||||
|
||||
public static final String RESTART_KEY = "CompositeKeySqlDrivingQueryItemReader.key";
|
||||
public static final String RESTART_KEY = "key";
|
||||
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@@ -47,20 +48,20 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
private String sql;
|
||||
|
||||
private String restartSql;
|
||||
|
||||
|
||||
public MultipleColumnJdbcKeyGenerator() {
|
||||
super();
|
||||
setName(MultipleColumnJdbcKeyGenerator.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new ItemReader.
|
||||
*
|
||||
*
|
||||
* @param jdbcTemplate
|
||||
* @param sql - Sql statement that returns all keys to process.
|
||||
* @param keyMapper - RowMapper that maps each row of the ResultSet to an object.
|
||||
* @param keyMapper - RowMapper that maps each row of the ResultSet to an
|
||||
* object.
|
||||
*/
|
||||
public MultipleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate,
|
||||
String sql){
|
||||
public MultipleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate, String sql) {
|
||||
this();
|
||||
Assert.notNull(jdbcTemplate, "The JdbcTemplate must not be null.");
|
||||
Assert.hasText(sql, "The DrivingQuery must not be null or empty.");
|
||||
@@ -69,24 +70,26 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.io.sql.scratch.AbstractDrivingQueryItemReader#retrieveKeys()
|
||||
*/
|
||||
public List retrieveKeys(ExecutionContext executionContext) {
|
||||
|
||||
|
||||
Assert.state(keyMapper != null, "KeyMapper must not be null.");
|
||||
Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty" +
|
||||
" in order to restart.");
|
||||
Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty"
|
||||
+ " in order to restart.");
|
||||
|
||||
if (executionContext.size() > 0) {
|
||||
return jdbcTemplate.query(restartSql, keyMapper.createSetter(executionContext), keyMapper);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return jdbcTemplate.query(sql, keyMapper);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object)
|
||||
*/
|
||||
public void saveState(Object key, ExecutionContext executionContext) {
|
||||
@@ -97,14 +100,15 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
/**
|
||||
* Set the query to use to retrieve keys in order to restore the previous
|
||||
* state for restart.
|
||||
*
|
||||
*
|
||||
* @param restartQuery
|
||||
*/
|
||||
public void setRestartSql(String restartQuery) {
|
||||
this.restartSql = restartQuery;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -112,7 +116,7 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
Assert.hasText(sql, "The DrivingQuery must not be null or empty.");
|
||||
Assert.notNull(keyMapper, "The key RowMapper must not be null.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the {@link ExecutionContextRowMapper} to be used to map a resultset
|
||||
* to keys.
|
||||
@@ -122,7 +126,7 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
public void setKeyMapper(ExecutionContextRowMapper keyMapper) {
|
||||
this.keyMapper = keyMapper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the sql statement used to generate the keys list.
|
||||
*
|
||||
@@ -131,7 +135,7 @@ public class MultipleColumnJdbcKeyGenerator implements
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
|
||||
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ package org.springframework.batch.io.driving.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.ClassUtils;
|
||||
import org.springframework.batch.io.driving.KeyGenerator;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.SingleColumnRowMapper;
|
||||
@@ -50,9 +50,9 @@ import org.springframework.util.StringUtils;
|
||||
* @author Lucas Ward
|
||||
* @since 1.0
|
||||
*/
|
||||
public class SingleColumnJdbcKeyGenerator implements KeyGenerator {
|
||||
public class SingleColumnJdbcKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator {
|
||||
|
||||
public static final String RESTART_KEY = ClassUtils.getShortClassName(SingleColumnJdbcKeyGenerator.class) + ".key";
|
||||
public static final String RESTART_KEY = "key";
|
||||
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class SingleColumnJdbcKeyGenerator implements KeyGenerator {
|
||||
private RowMapper keyMapper = new SingleColumnRowMapper();
|
||||
|
||||
public SingleColumnJdbcKeyGenerator() {
|
||||
super();
|
||||
setName(SingleColumnJdbcKeyGenerator.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.batch.io.file.transform.AbstractLineTokenizer;
|
||||
import org.springframework.batch.io.file.transform.DelimitedLineTokenizer;
|
||||
import org.springframework.batch.io.file.transform.LineTokenizer;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.exception.StreamException;
|
||||
@@ -63,7 +64,7 @@ import org.springframework.util.Assert;
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class FlatFileItemReader implements ItemReader, Skippable, ItemStream, InitializingBean {
|
||||
public class FlatFileItemReader extends ExecutionContextUserSupport implements ItemReader, Skippable, ItemStream, InitializingBean {
|
||||
|
||||
private static Log log = LogFactory.getLog(FlatFileItemReader.class);
|
||||
|
||||
@@ -93,14 +94,16 @@ public class FlatFileItemReader implements ItemReader, Skippable, ItemStream, In
|
||||
private LineTokenizer tokenizer = new DelimitedLineTokenizer();
|
||||
|
||||
private FieldSetMapper fieldSetMapper;
|
||||
|
||||
private String name = FlatFileItemReader.class.getName();
|
||||
|
||||
/**
|
||||
* Encapsulates the state of the input source. If it is null then we are
|
||||
* uninitialized.
|
||||
*/
|
||||
private LineReader reader;
|
||||
|
||||
public FlatFileItemReader() {
|
||||
setName(FlatFileItemReader.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the reader if necessary.
|
||||
@@ -366,9 +369,5 @@ public class FlatFileItemReader implements ItemReader, Skippable, ItemStream, In
|
||||
Assert.notNull(resource, "Input resource must not be null");
|
||||
Assert.notNull(fieldSetMapper, "FieldSetMapper must not be null.");
|
||||
}
|
||||
|
||||
private String getKey(String key){
|
||||
return name + "." + key;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.batch.io.file.mapping.FieldSetCreator;
|
||||
import org.springframework.batch.io.file.transform.DelimitedLineAggregator;
|
||||
import org.springframework.batch.io.file.transform.LineAggregator;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
@@ -65,7 +66,7 @@ import org.springframework.util.Assert;
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class FlatFileItemWriter implements ItemWriter, ItemStream,
|
||||
public class FlatFileItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream,
|
||||
InitializingBean {
|
||||
|
||||
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
@@ -84,7 +85,9 @@ public class FlatFileItemWriter implements ItemWriter, ItemStream,
|
||||
|
||||
private FieldSetCreator fieldSetCreator;
|
||||
|
||||
private String name = FlatFileItemWriter.class.getName();
|
||||
public FlatFileItemWriter() {
|
||||
setName(FlatFileItemWriter.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that mandatory properties (resource) are set.
|
||||
@@ -483,11 +486,4 @@ public class FlatFileItemWriter implements ItemWriter, ItemStream,
|
||||
getOutputState().mark();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String getKey(String key){
|
||||
return name + "." + key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader;
|
||||
import org.springframework.batch.io.xml.stax.FragmentEventReader;
|
||||
import org.springframework.batch.io.xml.stax.TransactionalEventReader;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.exception.StreamException;
|
||||
@@ -35,10 +36,10 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class StaxEventItemReader implements ItemReader, Skippable, ItemStream,
|
||||
public class StaxEventItemReader extends ExecutionContextUserSupport implements ItemReader, Skippable, ItemStream,
|
||||
InitializingBean {
|
||||
|
||||
public static final String READ_COUNT_STATISTICS_NAME = "StaxEventReaderItemReader.readCount";
|
||||
public static final String READ_COUNT_STATISTICS_NAME = "readCount";
|
||||
|
||||
private FragmentEventReader fragmentReader;
|
||||
|
||||
@@ -62,6 +63,10 @@ public class StaxEventItemReader implements ItemReader, Skippable, ItemStream,
|
||||
|
||||
private boolean saveState = false;
|
||||
|
||||
public StaxEventItemReader() {
|
||||
setName(StaxEventItemReader.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the next root element from the file, and return it.
|
||||
*
|
||||
@@ -127,8 +132,8 @@ public class StaxEventItemReader implements ItemReader, Skippable, ItemStream,
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
if (executionContext.containsKey(READ_COUNT_STATISTICS_NAME)) {
|
||||
long restoredRecordCount = executionContext.getLong(READ_COUNT_STATISTICS_NAME);
|
||||
if (executionContext.containsKey(getKey(READ_COUNT_STATISTICS_NAME))) {
|
||||
long restoredRecordCount = executionContext.getLong(getKey(READ_COUNT_STATISTICS_NAME));
|
||||
int REASONABLE_ADHOC_COMMIT_FREQUENCY = 100;
|
||||
while (currentRecordCount <= restoredRecordCount) {
|
||||
currentRecordCount++;
|
||||
@@ -196,7 +201,7 @@ public class StaxEventItemReader implements ItemReader, Skippable, ItemStream,
|
||||
public void update(ExecutionContext executionContext) {
|
||||
if(saveState){
|
||||
Assert.notNull(executionContext, "ExecutionContext must not be null");
|
||||
executionContext.putLong(READ_COUNT_STATISTICS_NAME, currentRecordCount);
|
||||
executionContext.putLong(getKey(READ_COUNT_STATISTICS_NAME), currentRecordCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.xml.stream.XMLStreamException;
|
||||
import org.springframework.batch.io.support.FileUtils;
|
||||
import org.springframework.batch.io.xml.stax.NoStartEndDocumentStreamWriter;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ExecutionContextUserSupport;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.exception.ClearFailedException;
|
||||
@@ -37,7 +38,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Peter Zozom
|
||||
*
|
||||
*/
|
||||
public class StaxEventItemWriter implements ItemWriter, ItemStream, InitializingBean {
|
||||
public class StaxEventItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream, InitializingBean {
|
||||
|
||||
// default encoding
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
@@ -49,10 +50,10 @@ public class StaxEventItemWriter implements ItemWriter, ItemStream, Initializing
|
||||
private static final String DEFAULT_ROOT_TAG_NAME = "root";
|
||||
|
||||
// restart data property name
|
||||
public static final String RESTART_DATA_NAME = "staxstreamoutputsource.position";
|
||||
public static final String RESTART_DATA_NAME = "position";
|
||||
|
||||
// restart data property name
|
||||
public static final String WRITE_STATISTICS_NAME = "staxstreamoutputsource.record.count";
|
||||
public static final String WRITE_STATISTICS_NAME = "record.count";
|
||||
|
||||
// file system resource
|
||||
private Resource resource;
|
||||
@@ -101,10 +102,12 @@ public class StaxEventItemWriter implements ItemWriter, ItemStream, Initializing
|
||||
// current count of processed records
|
||||
private long currentRecordCount = 0;
|
||||
|
||||
private String name = StaxEventItemWriter.class.getName();
|
||||
|
||||
private boolean saveState = false;
|
||||
|
||||
public StaxEventItemWriter() {
|
||||
setName(StaxEventItemWriter.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set output file.
|
||||
*
|
||||
@@ -448,13 +451,5 @@ public class StaxEventItemWriter implements ItemWriter, ItemStream, Initializing
|
||||
public void setSaveState(boolean saveState) {
|
||||
this.saveState = saveState;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String getKey(String key){
|
||||
return name + "." + key;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.batch.item;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Facilitates assigning names to objects persisting data in
|
||||
* {@link ExecutionContext} and generating keys for {@link ExecutionContext}
|
||||
* based on the name.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class ExecutionContextUserSupport {
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @param name unique name for the item stream used to create execution
|
||||
* context keys.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix the argument with the name of the item stream to create a unique
|
||||
* key that can be safely used to identify data stored in
|
||||
* {@link ExecutionContext}.
|
||||
*/
|
||||
protected String getKey(String s) {
|
||||
Assert.hasLength(name, "ItemStream must have a name assigned.");
|
||||
return name + "." + s;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user