[BATCH-383] Fixes to make Spring Batch 1.4 runtime compliant.

This commit is contained in:
nebhale
2008-03-11 13:49:17 +00:00
parent 32e25b081c
commit 9f7cc87c0d
40 changed files with 500 additions and 564 deletions

View File

@@ -29,27 +29,27 @@ import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.Skippable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* {@link ItemReader} for reading database records built on top of Hibernate.
*
* It executes the HQL {@link #queryString} when initialized and iterates over
* the result set as {@link #read()} method is called, returning an object
* corresponding to current row.
* It executes the HQL {@link #queryString} when initialized and iterates over the result set as {@link #read()} method
* is called, returning an object corresponding to current row.
*
* Input source can be configured to use either {@link StatelessSession}
* sufficient for simple mappings without the need to cascade to associated
* objects or standard hibernate {@link Session} for more advanced mappings or
* when caching is desired.
* Input source can be configured to use either {@link StatelessSession} sufficient for simple mappings without the need
* to cascade to associated objects or standard hibernate {@link Session} for more advanced mappings or when caching is
* desired.
*
* When stateful session is used it will be cleared after successful commit
* without being flushed (no inserts or updates are expected).
* When stateful session is used it will be cleared after successful commit without being flushed (no inserts or updates
* are expected).
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public class HibernateCursorItemReader extends ExecutionContextUserSupport implements ItemReader, ItemStream, Skippable, InitializingBean {
public class HibernateCursorItemReader extends ExecutionContextUserSupport implements ItemReader, ItemStream,
Skippable, InitializingBean {
private static final String RESTART_DATA_ROW_NUMBER_KEY = "row.number";
@@ -77,12 +77,11 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
private int currentProcessedRow = 0;
private boolean initialized = false;
private boolean saveState = false;
public HibernateCursorItemReader() {
setName(HibernateCursorItemReader.class.getSimpleName());
setName(ClassUtils.getShortName(HibernateCursorItemReader.class));
}
public Object read() {
@@ -117,8 +116,7 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
skipCount = 0;
if (useStatelessSession) {
statelessSession.close();
}
else {
} else {
statefulSession.close();
}
}
@@ -132,20 +130,20 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
if (useStatelessSession) {
statelessSession = sessionFactory.openStatelessSession();
cursor = statelessSession.createQuery(queryString).scroll();
}
else {
} else {
statefulSession = sessionFactory.openSession();
cursor = statefulSession.createQuery(queryString).scroll();
}
initialized = true;
if (executionContext.containsKey(getKey(RESTART_DATA_ROW_NUMBER_KEY))) {
currentProcessedRow = Integer.parseInt(executionContext.getString(getKey(RESTART_DATA_ROW_NUMBER_KEY)));
cursor.setRowNumber(currentProcessedRow - 1);
}
if (executionContext.containsKey(getKey(SKIPPED_ROWS))) {
String[] skipped = StringUtils.commaDelimitedListToStringArray(executionContext.getString(getKey(SKIPPED_ROWS)));
String[] skipped = StringUtils.commaDelimitedListToStringArray(executionContext
.getString(getKey(SKIPPED_ROWS)));
for (int i = 0; i < skipped.length; i++) {
this.skippedRows.add(new Integer(skipped[i]));
}
@@ -174,9 +172,8 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
/**
* Can be set only in uninitialized state.
*
* @param useStatelessSession <code>true</code> to use
* {@link StatelessSession} <code>false</code> to use standard hibernate
* {@link Session}
* @param useStatelessSession <code>true</code> to use {@link StatelessSession} <code>false</code> to use
* standard hibernate {@link Session}
*/
public void setUseStatelessSession(boolean useStatelessSession) {
Assert.state(!initialized);
@@ -186,7 +183,7 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
/**
*/
public void update(ExecutionContext executionContext) {
if(saveState){
if (saveState) {
Assert.notNull(executionContext, "ExecutionContext must not be null");
executionContext.putString(getKey(RESTART_DATA_ROW_NUMBER_KEY), "" + currentProcessedRow);
String skipped = skippedRows.toString();
@@ -195,10 +192,8 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
}
/**
* Skip the current row. If the transaction is rolled back, this row will
* not be represented when read() is called. For example, if you read in row
* 2, find the data to be bad, and call skip(), then continue processing and
* find
* Skip the current row. If the transaction is rolled back, this row will not be represented when read() is called.
* For example, if you read in row 2, find the data to be bad, and call skip(), then continue processing and find
*/
public void skip() {
skippedRows.add(new Integer(currentProcessedRow));
@@ -206,10 +201,8 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
}
/**
* Mark is supported as long as this {@link ItemStream} is used in a
* single-threaded environment. The state backing the mark is a single
* counter, keeping track of the current position, so multiple threads
* cannot be accommodated.
* Mark is supported as long as this {@link ItemStream} is used in a single-threaded environment. The state backing
* the mark is a single counter, keeping track of the current position, so multiple threads cannot be accommodated.
*
* @see org.springframework.batch.item.ItemReader#mark()
*/
@@ -222,20 +215,20 @@ public class HibernateCursorItemReader extends ExecutionContextUserSupport impl
/*
* (non-Javadoc)
*
* @see org.springframework.batch.item.stream.ItemStreamAdapter#reset(org.springframework.batch.item.ExecutionContext)
*/
public void reset() {
currentProcessedRow = lastCommitRowNumber;
if (lastCommitRowNumber == 0) {
cursor.beforeFirst();
}
else {
} else {
// Set the cursor so that next time it is advanced it will
// come back to the committed row.
cursor.setRowNumber(lastCommitRowNumber - 1);
}
}
public void setSaveState(boolean saveState) {
this.saveState = saveState;
}

View File

@@ -44,6 +44,7 @@ import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import org.springframework.jdbc.support.SQLExceptionTranslator;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -143,7 +144,7 @@ public class JdbcCursorItemReader extends ExecutionContextUserSupport implements
private boolean saveState = false;
public JdbcCursorItemReader() {
setName(JdbcCursorItemReader.class.getSimpleName());
setName(ClassUtils.getShortName(JdbcCursorItemReader.class));
}
/**

View File

@@ -8,6 +8,7 @@ import org.springframework.batch.item.database.DrivingQueryItemReader;
import org.springframework.batch.item.database.KeyCollector;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.ibatis.sqlmap.client.SqlMapClient;
@@ -33,7 +34,7 @@ public class IbatisKeyCollector extends ExecutionContextUserSupport implements K
private String restartQueryId;
public IbatisKeyCollector() {
setName(IbatisKeyCollector.class.getSimpleName());
setName(ClassUtils.getShortName(IbatisKeyCollector.class));
}
/*

View File

@@ -24,27 +24,24 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* <p>
* Jdbc {@link KeyCollector} implementation that only works for a single column
* key. A sql query must be passed in which will be used to return a list of
* keys. Each key will be mapped by a {@link RowMapper} that returns a mapped
* key. By default, the {@link SingleColumnRowMapper} is used, and will convert
* keys into well known types at runtime. It is extremely important to note that
* only one column should be mapped to an object and returned as a key. If
* multiple columns are returned as a key in this strategy, then restart will
* not function properly. Instead a strategy that supports keys comprised of
* multiple columns should be used.</p>
* Jdbc {@link KeyCollector} implementation that only works for a single column key. A sql query must be passed in which
* will be used to return a list of keys. Each key will be mapped by a {@link RowMapper} that returns a mapped key. By
* default, the {@link SingleColumnRowMapper} is used, and will convert keys into well known types at runtime. It is
* extremely important to note that only one column should be mapped to an object and returned as a key. If multiple
* columns are returned as a key in this strategy, then restart will not function properly. Instead a strategy that
* supports keys comprised of multiple columns should be used.
* </p>
*
* <p>
* Restartability: Because the key is only one column, restart is made much more
* simple. Before each commit, the last processed key is returned to be stored
* as restart data. Upon restart, that same key is given back to restore from,
* using a separate 'RestartQuery'. This means that only the keys remaining to
* be processed are returned, rather than returning the original list of keys
* and iterating forward to that last committed point.
* Restartability: Because the key is only one column, restart is made much more simple. Before each commit, the last
* processed key is returned to be stored as restart data. Upon restart, that same key is given back to restore from,
* using a separate 'RestartQuery'. This means that only the keys remaining to be processed are returned, rather than
* returning the original list of keys and iterating forward to that last committed point.
* </p>
*
* @author Lucas Ward
@@ -63,12 +60,12 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
private RowMapper keyMapper = new SingleColumnRowMapper();
public SingleColumnJdbcKeyCollector() {
setName(SingleColumnJdbcKeyCollector.class.getSimpleName());
setName(ClassUtils.getShortName(SingleColumnJdbcKeyCollector.class));
}
/**
* Constructs a new instance using the provided jdbcTemplate and string
* representing the sql statement that should be used to retrieve keys.
* Constructs a new instance using the provided jdbcTemplate and string representing the sql statement that should
* be used to retrieve keys.
*
* @param jdbcTemplate
* @param sql
@@ -85,18 +82,18 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
/*
* (non-Javadoc)
*
* @see org.springframework.batch.io.driving.KeyGenerationStrategy#retrieveKeys()
*/
public List retrieveKeys(ExecutionContext executionContext) {
Assert.notNull(executionContext, "The ExecutionContext must not be null");
if (executionContext.containsKey(RESTART_KEY)) {
Assert.state(StringUtils.hasText(restartSql), "The restart sql query must not be null or empty"
+ " in order to restart.");
+ " in order to restart.");
return jdbcTemplate.query(restartSql, new Object[] { executionContext.get(RESTART_KEY) }, keyMapper);
}
else{
} else {
return jdbcTemplate.query(sql, keyMapper);
}
}
@@ -115,6 +112,7 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
@@ -132,8 +130,7 @@ public class SingleColumnJdbcKeyCollector extends ExecutionContextUserSupport im
}
/**
* Set the SQL query to be used to return the remaining keys to be
* processed.
* Set the SQL query to be used to return the remaining keys to be processed.
*
* @param restartSql
*/

View File

@@ -41,6 +41,7 @@ import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* This class represents a {@link ItemReader}, that reads lines from text file, tokenizes them to structured tuples ({@link FieldSet}s)
@@ -100,7 +101,7 @@ public class FlatFileItemReader extends ExecutionContextUserSupport implements I
private LineReader reader;
public FlatFileItemReader() {
setName(FlatFileItemReader.class.getSimpleName());
setName(ClassUtils.getShortName(FlatFileItemReader.class));
}
/**
@@ -258,9 +259,8 @@ public class FlatFileItemReader extends ExecutionContextUserSupport implements I
throw e;
} catch (ItemReaderException e) {
throw e;
}
catch (Exception e) {
throw new IllegalStateException(e);
} catch (Exception e) {
throw new IllegalStateException();
}
}

View File

@@ -42,6 +42,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* This class is an output target that writes data to a file or stream. The writer also provides restart, statistics and
@@ -81,7 +82,7 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implements I
private FieldSetCreator fieldSetCreator;
public FlatFileItemWriter() {
setName(FlatFileItemWriter.class.getSimpleName());
setName(ClassUtils.getShortName(FlatFileItemWriter.class));
}
/**

View File

@@ -96,12 +96,12 @@ public class RecursiveCollectionItemTransformer implements ItemTransformer {
private static class TransformHolder {
StringBuilder builder = new StringBuilder();
StringBuffer builder = new StringBuffer();
TransformHolder() {
}
TransformHolder(StringBuilder builder) {
TransformHolder(StringBuffer builder) {
this.builder = builder;
}
}

View File

@@ -26,19 +26,19 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Input source for reading XML input based on StAX.
*
* It extracts fragments from the input XML document which correspond to records
* for processing. The fragments are wrapped with StartDocument and EndDocument
* events so that the fragments can be further processed like standalone XML
* It extracts fragments from the input XML document which correspond to records for processing. The fragments are
* wrapped with StartDocument and EndDocument events so that the fragments can be further processed like standalone XML
* documents.
*
* @author Robert Kasanicky
*/
public class StaxEventItemReader extends ExecutionContextUserSupport implements ItemReader, Skippable, ItemStream,
InitializingBean {
InitializingBean {
private static final String READ_COUNT_STATISTICS_NAME = "read.count";
@@ -61,13 +61,13 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
private long currentRecordCount = 0;
private List skipRecords = new ArrayList();
private boolean saveState = false;
public StaxEventItemReader() {
setName(StaxEventItemReader.class.getSimpleName());
setName(ClassUtils.getShortName(StaxEventItemReader.class));
}
/**
* Read in the next root element from the file, and return it.
*
@@ -103,14 +103,11 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
try {
fragmentReader.close();
inputStream.close();
}
catch (XMLStreamException e) {
} catch (XMLStreamException e) {
throw new DataAccessResourceFailureException("Error while closing event reader", e);
}
catch (IOException e) {
} catch (IOException e) {
throw new DataAccessResourceFailureException("Error while closing input stream", e);
}
finally {
} finally {
fragmentReader = null;
inputStream = null;
}
@@ -122,17 +119,15 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
try {
inputStream = resource.getInputStream();
txReader = new DefaultTransactionalEventReader(XMLInputFactory.newInstance().createXMLEventReader(
inputStream));
inputStream));
fragmentReader = new DefaultFragmentEventReader(txReader);
}
catch (XMLStreamException xse) {
} catch (XMLStreamException xse) {
throw new DataAccessResourceFailureException("Unable to create XML reader", xse);
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw new DataAccessResourceFailureException("Unable to get input stream", ioe);
}
initialized = true;
if (executionContext.containsKey(getKey(READ_COUNT_STATISTICS_NAME))) {
long restoredRecordCount = executionContext.getLong(getKey(READ_COUNT_STATISTICS_NAME));
int REASONABLE_ADHOC_COMMIT_FREQUENCY = 100;
@@ -156,24 +151,22 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
}
/**
* @param eventReaderDeserializer maps xml fragments corresponding to
* records to objects
* @param eventReaderDeserializer maps xml fragments corresponding to records to objects
*/
public void setFragmentDeserializer(EventReaderDeserializer eventReaderDeserializer) {
this.eventReaderDeserializer = eventReaderDeserializer;
}
/**
* @param fragmentRootElementName name of the root element of the fragment
* TODO String can be ambiguous due to namespaces, use QName?
* @param fragmentRootElementName name of the root element of the fragment TODO String can be ambiguous due to
* namespaces, use QName?
*/
public void setFragmentRootElementName(String fragmentRootElementName) {
this.fragmentRootElementName = fragmentRootElementName;
}
/**
* Mark the last read record as 'skipped', so that I will not be returned
* from read() in the case of a rollback.
* Mark the last read record as 'skipped', so that I will not be returned from read() in the case of a rollback.
*
* @see Skippable#skip()
*/
@@ -182,12 +175,11 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
}
/**
* Ensure that all required dependencies for the ItemReader to run are
* provided after all properties have been set.
* Ensure that all required dependencies for the ItemReader to run are provided after all properties have been set.
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
* @throws IllegalArgumentException if the Resource, FragmentDeserializer or
* FragmentRootElementName is null, or if the root element is empty.
* @throws IllegalArgumentException if the Resource, FragmentDeserializer or FragmentRootElementName is null, or if
* the root element is empty.
* @throws IllegalStateException if the Resource does not exist.
*/
public void afterPropertiesSet() throws Exception {
@@ -200,22 +192,19 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
* @see ItemStream#update(ExecutionContext)
*/
public void update(ExecutionContext executionContext) {
if(saveState){
if (saveState) {
Assert.notNull(executionContext, "ExecutionContext must not be null");
executionContext.putLong(getKey(READ_COUNT_STATISTICS_NAME), currentRecordCount);
}
}
/**
* Responsible for moving the cursor before the StartElement of the fragment
* root.
* Responsible for moving the cursor before the StartElement of the fragment root.
*
* This implementation simply looks for the next corresponding element, it
* does not care about element nesting. You will need to override this
* method to correctly handle composite fragments.
* This implementation simply looks for the next corresponding element, it does not care about element nesting. You
* will need to override this method to correctly handle composite fragments.
*
* @return <code>true</code> if next fragment was found,
* <code>false</code> otherwise.
* @return <code>true</code> if next fragment was found, <code>false</code> otherwise.
*/
protected boolean moveCursorToNextFragment(XMLEventReader reader) {
try {
@@ -229,23 +218,19 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
QName startElementName = ((StartElement) reader.peek()).getName();
if (startElementName.getLocalPart().equals(fragmentRootElementName)) {
return true;
}
else {
} else {
reader.nextEvent();
}
}
}
catch (XMLStreamException e) {
} catch (XMLStreamException e) {
throw new DataAccessResourceFailureException("Error while reading from event reader", e);
}
}
/**
* Mark is supported as long as this {@link ItemStream} is used in a
* single-threaded environment. The state backing the mark is a single
* counter, keeping track of the current position, so multiple threads
* cannot be accommodated.
*
* Mark is supported as long as this {@link ItemStream} is used in a single-threaded environment. The state backing
* the mark is a single counter, keeping track of the current position, so multiple threads cannot be accommodated.
*
* @see org.springframework.batch.item.AbstractItemReader#mark()
*/
public void mark() {
@@ -256,6 +241,7 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements
/*
* (non-Javadoc)
*
* @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext)
*/
public void reset() {

View File

@@ -27,24 +27,23 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
/**
* An implementation of {@link ItemWriter} which uses StAX and
* {@link EventWriterSerializer} for serializing object to XML.
* An implementation of {@link ItemWriter} which uses StAX and {@link EventWriterSerializer} for serializing object to
* XML.
*
* This item writer also provides restart, statistics and transaction features
* by implementing corresponding interfaces.
* This item writer also provides restart, statistics and transaction features by implementing corresponding interfaces.
*
* Output is buffered until {@link #flush()} is called - only then the actual
* writing to file takes place.
* Output is buffered until {@link #flush()} is called - only then the actual writing to file takes place.
*
* @author Peter Zozom
* @author Robert Kasanicky
*
*/
public class StaxEventItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream,
InitializingBean {
InitializingBean {
// default encoding
private static final String DEFAULT_ENCODING = "UTF-8";
@@ -112,7 +111,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
private List buffer = new ArrayList();
public StaxEventItemWriter() {
setName(StaxEventItemWriter.class.getSimpleName());
setName(ClassUtils.getShortName(StaxEventItemWriter.class));
}
/**
@@ -179,8 +178,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
}
/**
* Set the tag name of the root element. If not set, default name is used
* ("root").
* Set the tag name of the root element. If not set, default name is used ("root").
*
* @param rootTagName the tag name to be used for the root element
*/
@@ -207,8 +205,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
}
/**
* Set "overwrite" flag for the output file. Flag is ignored when output
* file processing is restarted.
* Set "overwrite" flag for the output file. Flag is ignored when output file processing is restarted.
*
* @param shouldDeleteIfExists
*/
@@ -257,8 +254,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
os = new FileOutputStream(file, true);
channel = os.getChannel();
setPosition(position);
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", ioe);
}
@@ -270,8 +266,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
if (!restarted) {
startDocument(delegateEventWriter);
}
}
catch (XMLStreamException xse) {
} catch (XMLStreamException xse) {
throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", xse);
}
@@ -283,8 +278,8 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
* <li>xml declaration - defines encoding and XML version</li>
* <li>opening tag of the root element and its attributes</li>
* </ul>
* If this is not sufficient for you, simply override this method. Encoding,
* version and root tag name can be retrieved with corresponding getters.
* If this is not sufficient for you, simply override this method. Encoding, version and root tag name can be
* retrieved with corresponding getters.
*
* @param writer XML event writer
* @throws XMLStreamException
@@ -312,8 +307,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
}
/**
* Finishes the XML document. It closes any start tag and writes
* corresponding end tags.
* Finishes the XML document. It closes any start tag and writes corresponding end tags.
*
* @param writer XML event writer
* @throws XMLStreamException
@@ -326,8 +320,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
ByteBuffer bbuf = ByteBuffer.wrap(("</" + getRootTagName() + ">").getBytes());
try {
channel.write(bbuf);
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe);
}
}
@@ -343,11 +336,9 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
endDocument(delegateEventWriter);
eventWriter.close();
channel.close();
}
catch (XMLStreamException xse) {
} catch (XMLStreamException xse) {
throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", xse);
}
catch (IOException ioe) {
} catch (IOException ioe) {
throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe);
}
}
@@ -359,13 +350,14 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
* @see #flush()
*/
public void write(Object item) {
currentRecordCount++;
buffer.add(item);
}
/**
* Get the restart data.
*
* @see org.springframework.batch.item.ItemStream#update(ExecutionContext)
*/
public void update(ExecutionContext executionContext) {
@@ -378,8 +370,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
}
/*
* Get the actual position in file channel. This method flushes any buffered
* data before position is read.
* Get the actual position in file channel. This method flushes any buffered data before position is read.
*
* @return byte offset in file channel
*/
@@ -390,8 +381,7 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
try {
eventWriter.flush();
position = channel.position();
}
catch (Exception e) {
} catch (Exception e) {
throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e);
}
@@ -407,11 +397,10 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implements
try {
Assert.state(channel.size() >= lastCommitPointPosition,
"Current file size is smaller than size at last commit");
"Current file size is smaller than size at last commit");
channel.truncate(newPosition);
channel.position(newPosition);
}
catch (IOException e) {
} catch (IOException e) {
throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e);
}

View File

@@ -92,7 +92,7 @@ public class LogOrRethrowExceptionHandler implements ExceptionHandler {
DefaultExceptionHandler.rethrow(throwable);
} else {
throw new IllegalStateException(
"Unclassified exception encountered. Did you mean to classifiy this as 'rethrow'?", throwable);
"Unclassified exception encountered. Did you mean to classifiy this as 'rethrow'?");
}
}

View File

@@ -28,14 +28,11 @@ import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.util.Assert;
/**
* A {@link MethodInterceptor} that can be used to automatically repeat calls to
* a method on a service. The injected {@link RepeatOperations} is used to
* control the completion of the loop. By default it will repeat until the
* target method returns null. Be careful when injecting a bespoke
* {@link RepeatOperations} that the loop will actually terminate, because the
* default policy for a vanilla {@link RepeatTemplate} will never complete if
* the return type of the target method is void (the value returned is always
* not-null, representing the {@link Void#TYPE}).
* A {@link MethodInterceptor} that can be used to automatically repeat calls to a method on a service. The injected
* {@link RepeatOperations} is used to control the completion of the loop. By default it will repeat until the target
* method returns null. Be careful when injecting a bespoke {@link RepeatOperations} that the loop will actually
* terminate, because the default policy for a vanilla {@link RepeatTemplate} will never complete if the return type of
* the target method is void (the value returned is always not-null, representing the {@link Void#TYPE}).
*
* @author Dave Syer
*/
@@ -47,8 +44,7 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
* Setter for the {@link RepeatOperations}.
*
* @param batchTempate
* @throws IllegalArgumentException
* if the argument is null.
* @throws IllegalArgumentException if the argument is null.
*/
public void setRepeatOperations(RepeatOperations batchTempate) {
Assert.notNull(batchTempate, "'repeatOperations' cannot be null.");
@@ -56,8 +52,8 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
}
/**
* Invoke the proceeding method call repeatedly, according to the properties
* of the injected {@link RepeatOperations}.
* Invoke the proceeding method call repeatedly, according to the properties of the injected
* {@link RepeatOperations}.
*
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
@@ -65,22 +61,19 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
repeatOperations.iterate(new RepeatCallback() {
public ExitStatus doInIteration(RepeatContext context)
throws Exception {
public ExitStatus doInIteration(RepeatContext context) throws Exception {
try {
MethodInvocation clone = invocation;
if (invocation instanceof ProxyMethodInvocation) {
clone = ((ProxyMethodInvocation) invocation)
.invocableClone();
clone = ((ProxyMethodInvocation) invocation).invocableClone();
} else {
throw new IllegalStateException(
"MethodInvocation of the wrong type detected - this should not happen with Spring AOP, so please raise an issue if you see this exception");
"MethodInvocation of the wrong type detected - this should not happen with Spring AOP, so please raise an issue if you see this exception");
}
// N.B. discards return value if there is one
if (clone.getMethod().getGenericReturnType().equals(
Void.TYPE)) {
if (clone.getMethod().getReturnType().equals(Void.TYPE)) {
clone.proceed();
return ExitStatus.CONTINUABLE;
}
@@ -89,8 +82,7 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
if (e instanceof Exception) {
throw (Exception) e;
} else {
throw new RepeatException(
"Unexpected error in batch interceptor", e);
throw new RepeatException("Unexpected error in batch interceptor", e);
}
}
}

View File

@@ -26,13 +26,11 @@ import org.springframework.util.PropertiesPersister;
import org.springframework.util.StringUtils;
/**
* Utility to convert a Properties object to a String and back. Ideally this
* utility should have been used to convert to string in order to convert that
* string back to a Properties Object. Attempting to convert a string obtained
* by calling Properties.toString() will return an invalid Properties object.
* The format of Properties is that used by {@link PropertiesPersister} from the
* Spring Core, so a String in the correct format for a Spring property editor
* is fine (key=value pairs separated by new lines).
* Utility to convert a Properties object to a String and back. Ideally this utility should have been used to convert to
* string in order to convert that string back to a Properties Object. Attempting to convert a string obtained by
* calling Properties.toString() will return an invalid Properties object. The format of Properties is that used by
* {@link PropertiesPersister} from the Spring Core, so a String in the correct format for a Spring property editor is
* fine (key=value pairs separated by new lines).
*
* @author Lucas Ward
* @author Dave Syer
@@ -48,11 +46,9 @@ public final class PropertiesConverter {
};
/**
* Parse a String to a Properties object. If string is null, an empty
* Properties object will be returned. The input String is a set of
* name=value pairs, delimited by either newline or comma (for brevity). If
* the input String contains a newline it is assumed that the separator is
* newline, otherwise comma.
* Parse a String to a Properties object. If string is null, an empty Properties object will be returned. The input
* String is a set of name=value pairs, delimited by either newline or comma (for brevity). If the input String
* contains a newline it is assumed that the separator is newline, otherwise comma.
*
* @param stringToParse String to parse.
* @return Properties parsed from each string.
@@ -65,9 +61,9 @@ public final class PropertiesConverter {
return new Properties();
}
if (!stringToParse.contains("\n")) {
if (!contains(stringToParse, "\n")) {
return StringUtils.splitArrayElementsIntoProperties(StringUtils
.commaDelimitedListToStringArray(stringToParse), "=");
.commaDelimitedListToStringArray(stringToParse), "=");
}
StringReader stringReader = new StringReader(stringToParse);
@@ -78,20 +74,18 @@ public final class PropertiesConverter {
propertiesPersister.load(properties, stringReader);
// Exception is only thrown by StringReader after it is closed,
// so never in this case.
}
catch (IOException ex) {
} catch (IOException ex) {
throw new IllegalStateException("Error while trying to parse String to java.util.Properties,"
+ " given String: " + properties);
+ " given String: " + properties);
}
return properties;
}
/**
* Convert Properties object to String. This is only necessary for
* compatibility with converting the String back to a properties object. If
* an empty properties object is passed in, a blank string is returned,
* otherwise it's string representation is returned.
* Convert Properties object to String. This is only necessary for compatibility with converting the String back to
* a properties object. If an empty properties object is passed in, a blank string is returned, otherwise it's
* string representation is returned.
*
* @param propertiesToParse
* @return String representation of properties object
@@ -108,12 +102,15 @@ public final class PropertiesConverter {
try {
propertiesPersister.store(propertiesToParse, stringWriter, null);
}
catch (IOException ex) {
} catch (IOException ex) {
// Exception is never thrown by StringWriter
throw new IllegalStateException("Error while trying to convert properties to string");
}
return stringWriter.toString();
}
private static boolean contains(String str, String searchStr) {
return str.indexOf(searchStr) != -1;
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
/**
* Tests for {@link FlatFileItemReader} - skip and restart functionality.
@@ -40,7 +41,7 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
private ExecutionContext executionContext;
// simple stub instead of a realistic tokenizer
@@ -57,8 +58,7 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
};
/**
* Create inputFile, inject mock/stub dependencies for tested object,
* initialize the tested object
* Create inputFile, inject mock/stub dependencies for tested object, initialize the tested object
*/
protected void setUp() throws Exception {
@@ -83,6 +83,7 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
/**
* Test skip and skipRollback functionality
*
* @throws IOException
*/
public void testSkip() throws Exception {
@@ -118,6 +119,7 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
/**
* Test skip and skipRollback functionality
*
* @throws IOException
*/
public void testSkipFirstChunk() throws Exception {
@@ -160,8 +162,8 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
// get restart data
reader.update(executionContext);
assertEquals(4, executionContext.getLong(
FlatFileItemReader.class.getSimpleName() + ".lines.read.count"));
assertEquals(4, executionContext.getLong(ClassUtils.getShortName(FlatFileItemReader.class)
+ ".lines.read.count"));
// close input
reader.close(executionContext);
@@ -175,7 +177,8 @@ public class FlatFileItemReaderAdvancedTests extends TestCase {
assertEquals("[testLine6]", reader.read().toString());
reader.update(executionContext);
assertEquals(6, executionContext.getLong(FlatFileItemReader.class.getSimpleName() + ".lines.read.count"));
assertEquals(6, executionContext.getLong(ClassUtils.getShortName(FlatFileItemReader.class)
+ ".lines.read.count"));
}
}

View File

@@ -36,7 +36,7 @@ import org.springframework.core.io.Resource;
/**
* Tests for {@link FlatFileItemReader} - the fundamental item reading functionality.
*
*
* @see FlatFileItemReaderAdvancedTests
* @author Dave Syer
*/
@@ -48,7 +48,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
// common value used for writing to a file
private String TEST_STRING = "FlatFileInputTemplate-TestData";
private String TEST_OUTPUT = "[FlatFileInputTemplate-TestData]";
private ExecutionContext executionContext;
// simple stub instead of a realistic tokenizer
@@ -58,15 +58,14 @@ public class FlatFileItemReaderBasicTests extends TestCase {
}
};
private FieldSetMapper fieldSetMapper = new FieldSetMapper(){
private FieldSetMapper fieldSetMapper = new FieldSetMapper() {
public Object mapLine(FieldSet fs) {
return fs;
}
};
/**
* Create inputFile, inject mock/stub dependencies for tested object,
* initialize the tested object
* Create inputFile, inject mock/stub dependencies for tested object, initialize the tested object
*/
protected void setUp() throws Exception {
@@ -74,7 +73,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
itemReader.setLineTokenizer(tokenizer);
itemReader.setFieldSetMapper(fieldSetMapper);
itemReader.afterPropertiesSet();
executionContext = new ExecutionContext();
}
@@ -126,7 +125,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
}
public void testReadWithMapperError() throws Exception {
itemReader.setFieldSetMapper(new FieldSetMapper(){
itemReader.setFieldSetMapper(new FieldSetMapper() {
public Object mapLine(FieldSet fs) {
throw new RuntimeException("foo");
}
@@ -150,7 +149,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
itemReader.read();
fail("Expected ReaderNotOpenException");
} catch (ReaderNotOpenException e) {
assertTrue(e.getMessage().contains("open"));
assertTrue(contains(e.getMessage(), "open"));
}
}
@@ -169,8 +168,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
try {
itemReader.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected
}
}
@@ -196,8 +194,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
try {
itemReader.open(executionContext);
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected
}
}
@@ -209,8 +206,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
try {
itemReader.open(executionContext);
fail("Expected BatchEnvironmentException");
}
catch (ItemStreamException e) {
} catch (ItemStreamException e) {
// expected
assertEquals("foo", e.getCause().getMessage());
}
@@ -227,8 +223,8 @@ public class FlatFileItemReaderBasicTests extends TestCase {
}
public void testComments() throws Exception {
itemReader.setResource(getInputResource("% Comment\n"+TEST_STRING));
itemReader.setComments(new String[] {"%"});
itemReader.setResource(getInputResource("% Comment\n" + TEST_STRING));
itemReader.setComments(new String[] { "%" });
testRead();
}
@@ -237,7 +233,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
*/
public void testColumnNamesInHeader() throws Exception {
final String INPUT = "name1|name2\nvalue1|value2\nvalue3|value4";
itemReader = new FlatFileItemReader();
itemReader.setResource(getInputResource(INPUT));
itemReader.setLineTokenizer(new DelimitedLineTokenizer('|'));
@@ -245,11 +241,11 @@ public class FlatFileItemReaderBasicTests extends TestCase {
itemReader.setFirstLineIsHeader(true);
itemReader.afterPropertiesSet();
itemReader.open(executionContext);
FieldSet fs = (FieldSet) itemReader.read();
assertEquals("value1", fs.readString("name1"));
assertEquals("value2", fs.readString("name2"));
fs = (FieldSet) itemReader.read();
assertEquals("value3", fs.readString("name1"));
assertEquals("value4", fs.readString("name2"));
@@ -260,7 +256,7 @@ public class FlatFileItemReaderBasicTests extends TestCase {
*/
public void testLinesToSkip() throws Exception {
final String INPUT = "foo bar spam\none two\nthree four";
itemReader = new FlatFileItemReader();
itemReader.setResource(getInputResource(INPUT));
itemReader.setLineTokenizer(new DelimitedLineTokenizer(' '));
@@ -268,62 +264,66 @@ public class FlatFileItemReaderBasicTests extends TestCase {
itemReader.setLinesToSkip(1);
itemReader.afterPropertiesSet();
itemReader.open(executionContext);
FieldSet fs = (FieldSet) itemReader.read();
assertEquals("one", fs.readString(0));
assertEquals("two", fs.readString(1));
fs = (FieldSet) itemReader.read();
assertEquals("three", fs.readString(0));
assertEquals("four", fs.readString(1));
}
public void testNonExistantResource() throws Exception{
public void testNonExistantResource() throws Exception {
Resource resource = new NonExistentResource();
FlatFileItemReader testReader = new FlatFileItemReader();
testReader.setResource(resource);
testReader.setLineTokenizer(tokenizer);
testReader.setFieldSetMapper(fieldSetMapper);
testReader.setResource(resource);
//afterPropertiesSet should only throw an exception if the Resource is null
// afterPropertiesSet should only throw an exception if the Resource is null
testReader.afterPropertiesSet();
try{
try {
testReader.open(executionContext);
fail();
}catch(IllegalStateException ex){
//expected
} catch (IllegalStateException ex) {
// expected
}
}
public void testRuntimeFileCreation() throws Exception{
public void testRuntimeFileCreation() throws Exception {
Resource resource = new NonExistentResource();
FlatFileItemReader testReader = new FlatFileItemReader();
testReader.setResource(resource);
testReader.setLineTokenizer(tokenizer);
testReader.setFieldSetMapper(fieldSetMapper);
testReader.setResource(resource);
//afterPropertiesSet should only throw an exception if the Resource is null
// afterPropertiesSet should only throw an exception if the Resource is null
testReader.afterPropertiesSet();
//replace the resource to simulate runtime resource creation
// replace the resource to simulate runtime resource creation
testReader.setResource(getInputResource(TEST_STRING));
testReader.open(executionContext);
assertEquals(TEST_OUTPUT, testReader.read().toString());
}
private class NonExistentResource extends AbstractResource{
private boolean contains(String str, String searchStr) {
return str.indexOf(searchStr) != -1;
}
private class NonExistentResource extends AbstractResource {
public NonExistentResource() {
}
public boolean exists() {
return false;
}

View File

@@ -30,11 +30,11 @@ import org.springframework.batch.item.file.mapping.FieldSetCreator;
import org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper;
import org.springframework.core.io.FileSystemResource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.ClassUtils;
/**
* Tests of regular usage for {@link FlatFileItemWriter} Exception cases will be
* in separate TestCase classes with different <code>setUp</code> and
* <code>tearDown</code> methods
* Tests of regular usage for {@link FlatFileItemWriter} Exception cases will be in separate TestCase classes with
* different <code>setUp</code> and <code>tearDown</code> methods
*
* @author robert.kasanicky
* @author Dave Syer
@@ -53,12 +53,11 @@ public class FlatFileItemWriterTests extends TestCase {
// reads the output file to check the result
private BufferedReader reader;
private ExecutionContext executionContext;
/**
* Create temporary output file, define mock behaviour, set dependencies and
* initialize the object under test
* Create temporary output file, define mock behaviour, set dependencies and initialize the object under test
*/
protected void setUp() throws Exception {
@@ -87,9 +86,8 @@ public class FlatFileItemWriterTests extends TestCase {
}
/*
* Read a line from the output file, if the reader has not been created,
* recreate. This method is only necessary because running the tests in a
* UNIX environment locks the file if it's open for writing.
* Read a line from the output file, if the reader has not been created, recreate. This method is only necessary
* because running the tests in a UNIX environment locks the file if it's open for writing.
*/
private String readLine() throws IOException {
@@ -102,6 +100,7 @@ public class FlatFileItemWriterTests extends TestCase {
/**
* Regular usage of <code>write(String)</code> method
*
* @throws Exception
*/
public void testWriteString() throws Exception {
@@ -115,6 +114,7 @@ public class FlatFileItemWriterTests extends TestCase {
/**
* Regular usage of <code>write(String)</code> method
*
* @throws Exception
*/
public void testWriteWithConverter() throws Exception {
@@ -133,6 +133,7 @@ public class FlatFileItemWriterTests extends TestCase {
/**
* Regular usage of <code>write(String)</code> method
*
* @throws Exception
*/
public void testWriteWithConverterAndInfiniteLoop() throws Exception {
@@ -151,6 +152,7 @@ public class FlatFileItemWriterTests extends TestCase {
/**
* Regular usage of <code>write(String)</code> method
*
* @throws Exception
*/
public void testWriteWithConverterAndString() throws Exception {
@@ -167,6 +169,7 @@ public class FlatFileItemWriterTests extends TestCase {
/**
* Regular usage of <code>write(String[], LineDescriptor)</code> method
*
* @throws Exception
*/
public void testWriteRecord() throws Exception {
@@ -245,7 +248,7 @@ public class FlatFileItemWriterTests extends TestCase {
}
// 3 lines were written to the file after restart
assertEquals(3, executionContext.getLong(FlatFileItemWriter.class.getSimpleName() + ".written"));
assertEquals(3, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written"));
}
@@ -254,8 +257,7 @@ public class FlatFileItemWriterTests extends TestCase {
try {
inputSource.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected
}
}
@@ -269,7 +271,7 @@ public class FlatFileItemWriterTests extends TestCase {
inputSource.update(executionContext);
assertNotNull(executionContext);
assertEquals(3, executionContext.entrySet().size());
assertEquals(0, executionContext.getLong(FlatFileItemWriter.class.getSimpleName() + ".current.count"));
assertEquals(0, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".current.count"));
}
private void commit() throws Exception {

View File

@@ -21,6 +21,7 @@ import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.ClassUtils;
/**
* Tests for {@link StaxEventItemReader}.
@@ -38,7 +39,7 @@ public class StaxEventItemReaderTests extends TestCase {
private EventReaderDeserializer deserializer = new MockFragmentDeserializer();
private static final String FRAGMENT_ROOT_ELEMENT = "fragment";
private ExecutionContext executionContext;
protected void setUp() throws Exception {
@@ -55,8 +56,7 @@ public class StaxEventItemReaderTests extends TestCase {
try {
source.afterPropertiesSet();
fail();
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected;
}
@@ -65,8 +65,7 @@ public class StaxEventItemReaderTests extends TestCase {
try {
source.afterPropertiesSet();
fail();
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected
}
@@ -75,15 +74,14 @@ public class StaxEventItemReaderTests extends TestCase {
try {
source.afterPropertiesSet();
fail();
}
catch (IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
// expected
}
}
/**
* Regular usage scenario. ItemReader should pass XML fragments to
* deserializer wrapped with StartDocument and EndDocument events.
* Regular usage scenario. ItemReader should pass XML fragments to deserializer wrapped with StartDocument and
* EndDocument events.
*/
public void testFragmentWrapping() throws Exception {
source.afterPropertiesSet();
@@ -120,7 +118,7 @@ public class StaxEventItemReaderTests extends TestCase {
source.read();
source.update(executionContext);
System.out.println(executionContext);
assertEquals(1, executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count"));
assertEquals(1, executionContext.getLong(ClassUtils.getShortName(StaxEventItemReader.class) + ".read.count"));
List expectedAfterRestart = (List) source.read();
source = createNewInputSouce();
@@ -130,20 +128,18 @@ public class StaxEventItemReaderTests extends TestCase {
}
/**
* Restore point must not exceed end of file, input source must not be
* already initialised when restoring.
* Restore point must not exceed end of file, input source must not be already initialised when restoring.
*/
public void testInvalidRestore() {
ExecutionContext context = new ExecutionContext();
context.putLong(StaxEventItemReader.class.getSimpleName() + ".read.count", 100000);
context.putLong(ClassUtils.getShortName(StaxEventItemReader.class) + ".read.count", 100000);
try {
source.open(context);
fail("Expected StreamException");
}
catch (ItemStreamException e) {
} catch (ItemStreamException e) {
// expected
String message = e.getMessage();
assertTrue("Wrong message: "+message, message.contains("must be before"));
assertTrue("Wrong message: " + message, contains(message, "must be before"));
}
}
@@ -151,6 +147,7 @@ public class StaxEventItemReaderTests extends TestCase {
source.close(executionContext);
source.update(executionContext);
}
/**
* Skipping marked records after rollback.
*/
@@ -184,8 +181,7 @@ public class StaxEventItemReaderTests extends TestCase {
source.setFragmentDeserializer(new ExceptionFragmentDeserializer());
try {
source.read();
}
catch (Exception expected) {
} catch (Exception expected) {
source.reset();
}
source.setFragmentDeserializer(deserializer);
@@ -194,14 +190,13 @@ public class StaxEventItemReaderTests extends TestCase {
}
/**
* Statistics return the current record count. Calling read after end of
* input does not increase the counter.
* Statistics return the current record count. Calling read after end of input does not increase the counter.
*/
public void testExecutionContext() {
final int NUMBER_OF_RECORDS = 2;
source.open(executionContext);
source.update(executionContext);
for (int i = 0; i < NUMBER_OF_RECORDS; i++) {
long recordCount = extractRecordCount();
assertEquals(i, recordCount);
@@ -215,7 +210,7 @@ public class StaxEventItemReaderTests extends TestCase {
}
private long extractRecordCount() {
return executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count");
return executionContext.getLong(ClassUtils.getShortName(StaxEventItemReader.class) + ".read.count");
}
public void testCloseWithoutOpen() throws Exception {
@@ -243,8 +238,7 @@ public class StaxEventItemReaderTests extends TestCase {
try {
item = newSource.read();
fail("Expected ReaderNotOpenException");
}
catch (ReaderNotOpenException e) {
} catch (ReaderNotOpenException e) {
// expected
}
}
@@ -267,8 +261,7 @@ public class StaxEventItemReaderTests extends TestCase {
try {
source.open(executionContext);
}
catch (DataAccessResourceFailureException ex) {
} catch (DataAccessResourceFailureException ex) {
assertTrue(ex.getCause() instanceof IOException);
}
@@ -282,8 +275,7 @@ public class StaxEventItemReaderTests extends TestCase {
try {
source.open(executionContext);
fail();
}
catch (IllegalStateException ex) {
} catch (IllegalStateException ex) {
// expected
}
}
@@ -312,15 +304,14 @@ public class StaxEventItemReaderTests extends TestCase {
}
/**
* A simple XMLEvent deserializer mock - check for the start and end
* document events for the fragment root & end tags + skips the fragment
* contents.
* A simple XMLEvent deserializer mock - check for the start and end document events for the fragment root & end
* tags + skips the fragment contents.
*/
private static class MockFragmentDeserializer implements EventReaderDeserializer {
/**
* A simple mapFragment implementation checking the
* StaxEventReaderItemReader basic read functionality.
* A simple mapFragment implementation checking the StaxEventReaderItemReader basic read functionality.
*
* @param eventReader
* @return list of the events from fragment body
*/
@@ -348,8 +339,7 @@ public class StaxEventItemReaderTests extends TestCase {
XMLEvent event4 = eventReader.nextEvent();
assertTrue(event4.isEndDocument());
}
catch (XMLStreamException e) {
} catch (XMLStreamException e) {
throw new RuntimeException("Error occured in FragmentDeserializer", e);
}
return fragmentContent;
@@ -364,7 +354,7 @@ public class StaxEventItemReaderTests extends TestCase {
do {
eventInsideFragment = eventReader.peek();
if (eventInsideFragment instanceof EndElement
&& ((EndElement) eventInsideFragment).getName().getLocalPart().equals(FRAGMENT_ROOT_ELEMENT)) {
&& ((EndElement) eventInsideFragment).getName().getLocalPart().equals(FRAGMENT_ROOT_ELEMENT)) {
break;
}
events.add(eventReader.nextEvent());
@@ -375,6 +365,10 @@ public class StaxEventItemReaderTests extends TestCase {
}
private boolean contains(String str, String searchStr) {
return str.indexOf(searchStr) != -1;
}
/**
* Moves cursor inside the fragment body and causes rollback.
*/

View File

@@ -18,6 +18,7 @@ import org.springframework.core.io.Resource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.xml.transform.StaxResult;
/**
@@ -30,7 +31,7 @@ public class StaxEventItemWriterTests extends TestCase {
// output file
private Resource resource;
private ExecutionContext executionContext;
// test item for writing to output
@@ -40,7 +41,7 @@ public class StaxEventItemWriterTests extends TestCase {
}
};
private static final String TEST_STRING = StaxEventItemWriter.class.getSimpleName() + "-testString";
private static final String TEST_STRING = ClassUtils.getShortName(StaxEventItemWriter.class) + "-testString";
private static final int NOT_FOUND = -1;
@@ -62,20 +63,20 @@ public class StaxEventItemWriterTests extends TestCase {
// see asserts in the marshaller
writer.write(item);
assertFalse(marshaller.wasCalled);
writer.flush();
assertTrue(marshaller.wasCalled);
}
public void testClear() throws Exception {
writer.open(executionContext);
writer.write(item);
writer.write(item);
writer.clear();
//writer.write(item);
// writer.write(item);
writer.flush();
assertFalse(outputFileContent().contains(TEST_STRING));
assertFalse(contains(outputFileContent(), TEST_STRING));
}
/**
@@ -97,7 +98,7 @@ public class StaxEventItemWriterTests extends TestCase {
writer.write(item);
assertEquals("", outputFileContent());
writer.flush();
assertTrue(outputFileContent().contains(TEST_STRING));
assertTrue(contains(outputFileContent(), TEST_STRING));
}
/**
@@ -116,7 +117,7 @@ public class StaxEventItemWriterTests extends TestCase {
writer.open(executionContext);
writer.write(item);
writer.close(executionContext);
// check the output is concatenation of 'before restart' and 'after
// restart' writes.
String outputFile = outputFileContent();
@@ -139,7 +140,8 @@ public class StaxEventItemWriterTests extends TestCase {
for (int i = 1; i <= NUMBER_OF_RECORDS; i++) {
writer.write(item);
writer.update(executionContext);
long writeStatistics = executionContext.getLong(StaxEventItemWriter.class.getSimpleName() + ".record.count");
long writeStatistics = executionContext.getLong(ClassUtils.getShortName(StaxEventItemWriter.class)
+ ".record.count");
assertEquals(i, writeStatistics);
}
@@ -168,9 +170,9 @@ public class StaxEventItemWriterTests extends TestCase {
* Checks the received parameters.
*/
private class InputCheckMarshaller implements Marshaller {
boolean wasCalled = false;
public void marshal(Object graph, Result result) {
wasCalled = true;
assertTrue(result instanceof StaxResult);
@@ -192,8 +194,7 @@ public class StaxEventItemWriterTests extends TestCase {
StaxResult staxResult = (StaxResult) result;
try {
staxResult.getXMLEventWriter().add(XMLEventFactory.newInstance().createComment(graph.toString()));
}
catch (XMLStreamException e) {
} catch (XMLStreamException e) {
throw new RuntimeException("Exception while writing to output file", e);
}
}
@@ -228,7 +229,11 @@ public class StaxEventItemWriterTests extends TestCase {
source.setSaveState(true);
source.afterPropertiesSet();
return source;
}
private boolean contains(String str, String searchStr) {
return str.indexOf(searchStr) != -1;
}
}

View File

@@ -107,7 +107,6 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase {
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().toLowerCase().indexOf("unclassified")>=0);
assertEquals("Foo", e.getCause().getMessage());
}
}