Fixes the RepositoryItemReader ignoring explicitly set currentItemCount

If the user explicitly sets the currentItemCount value on a
RepositoryItemReader, prior to this commit, it is ignored.  this commit
addresses this by moving the current counter up to the correct value
when that value is set.  This fix addresses BATCH-2274.

This commit also addresses a number of compiler warnings around javadoc.
This commit is contained in:
Michael Minella
2014-10-16 16:51:52 -05:00
parent f865eb0135
commit 2ae6388c12
11 changed files with 131 additions and 54 deletions

View File

@@ -15,8 +15,14 @@
*/
package org.springframework.batch.item.data;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.adapter.AbstractMethodInvokingDelegator.InvocationTargetThrowableWrapper;
import org.springframework.batch.item.adapter.DynamicMethodInvocationException;
@@ -31,11 +37,6 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MethodInvoker;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* A {@link org.springframework.batch.item.ItemReader} that reads records utilizing
@@ -173,8 +174,8 @@ public class RepositoryItemReader<T> extends AbstractItemCountingItemStreamItemR
@Override
protected void jumpToItem(int itemLastIndex) throws Exception {
synchronized (lock) {
page = itemLastIndex / pageSize;
current = itemLastIndex % pageSize;
page = (itemLastIndex - 1) / pageSize;
current = (itemLastIndex - 1) % pageSize;
results = doPageRead();
page++;

View File

@@ -153,7 +153,7 @@ implements InitializingBean {
/**
* Public setter for the data source for injection purposes.
*
* @param dataSource
* @param dataSource {@link javax.sql.DataSource} to be used
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
@@ -172,7 +172,10 @@ implements InitializingBean {
* Prepare the given JDBC Statement (or PreparedStatement or
* CallableStatement), applying statement settings such as fetch size, max
* rows, and query timeout. @param stmt the JDBC Statement to prepare
* @throws SQLException
*
* @param stmt {@link java.sql.PreparedStatement} to be configured
*
* @throws SQLException if interactions with provided stmt fail
*
* @see #setFetchSize
* @see #setMaxRows
@@ -192,10 +195,10 @@ implements InitializingBean {
}
/**
* Return the exception translator for this instance.
*
* Creates a default SQLErrorCodeSQLExceptionTranslator for the specified
* DataSource if none is set.
*
* @return the exception translator for this instance.
*/
protected SQLExceptionTranslator getExceptionTranslator() {
synchronized(this) {
@@ -216,7 +219,7 @@ implements InitializingBean {
* warnings (at debug level).
*
* @param statement the current statement to obtain the warnings from, if there are any.
* @throws SQLException
* @throws SQLException if interaction with provided statement fails.
*
* @see org.springframework.jdbc.SQLWarningException
*/
@@ -461,7 +464,7 @@ implements InitializingBean {
* @param rs The current result set
* @param currentRow Current position of the result set
* @return the mapped object at the cursor position
* @throws SQLException
* @throws SQLException if interactions with the current result set fail
*/
protected abstract T readCursor(ResultSet rs, int currentRow) throws SQLException;

View File

@@ -16,15 +16,6 @@
package org.springframework.batch.item.database;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.ConnectionProxy;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.SmartDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.MethodInvoker;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -35,6 +26,16 @@ import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.ConnectionProxy;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.SmartDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.MethodInvoker;
/**
* Implementation of {@link SmartDataSource} that is capable of keeping a single
* JDBC Connection which is NOT closed after each use even if
@@ -105,6 +106,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi
/**
* Constructor that takes as a parameter with the {@link DataSource} to be
* wrapped.
*
* @param dataSource DataSource to be used
*/
public ExtendedConnectionDataSourceProxy(DataSource dataSource) {
this.dataSource = dataSource;

View File

@@ -129,6 +129,8 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
/**
* Open appropriate type of hibernate session and create the query.
*
* @return a Hibernate Query
*/
public Query createQuery() {
@@ -174,6 +176,8 @@ public class HibernateItemReaderHelper<T> implements InitializingBean {
* Scroll through the results up to the item specified.
*
* @param cursor the results to scroll over
* @param itemIndex index to scroll to
* @param flushInterval the number of items to scroll past before flushing
*/
public void jumpToItem(ScrollableResults cursor, int itemIndex, int flushInterval) {
for (int i = 0; i < itemIndex; i++) {

View File

@@ -122,8 +122,8 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
* Do perform the actual write operation using Hibernate's API.
* This can be overridden in a subclass if necessary.
*
* @param items
* the list of items to use for the write
* @param sessionFactory Hibernate SessionFactory to be used
* @param items the list of items to use for the write
*/
protected void doWrite(SessionFactory sessionFactory, List<? extends T> items) {
if (logger.isDebugEnabled()) {

View File

@@ -29,6 +29,7 @@ public interface ItemSqlParameterSourceProvider<T> {
* Provide parameter values in an {@link SqlParameterSource} based on values from
* the provided item.
* @param item the item to use for parameter values
* @return parameters extracted from the item
*/
SqlParameterSource createSqlParameterSource(T item);

View File

@@ -23,14 +23,14 @@ import org.springframework.ldap.core.LdapAttributes;
*
* @author Keith Barlow
*
* @param <T>
* @param <T> type the record will be mapped to
*/
public interface RecordMapper<T> {
/**
* Maps an {@link LdapAttributes LdapAttributes} object to the specified type.
*
* @param attributes
* @param attributes attributes
* @return object of type T
*/
T mapRecord(LdapAttributes attributes);

View File

@@ -154,20 +154,24 @@ public abstract class AbstractItemCountingItemStreamItemReader<T> extends Abstra
maxItemCount = executionContext.getInt(getExecutionContextKey(READ_COUNT_MAX));
}
int itemCount = 0;
if (executionContext.containsKey(getExecutionContextKey(READ_COUNT))) {
int itemCount = executionContext.getInt(getExecutionContextKey(READ_COUNT));
if (itemCount < maxItemCount) {
try {
jumpToItem(itemCount);
}
catch (Exception e) {
throw new ItemStreamException("Could not move to stored position on restart", e);
}
}
currentItemCount = itemCount;
itemCount = executionContext.getInt(getExecutionContextKey(READ_COUNT));
}
else if(currentItemCount > 0) {
itemCount = currentItemCount;
}
if (itemCount > 0 && itemCount < maxItemCount) {
try {
jumpToItem(itemCount);
}
catch (Exception e) {
throw new ItemStreamException("Could not move to stored position on restart", e);
}
}
currentItemCount = itemCount;
}

View File

@@ -50,7 +50,7 @@ public interface Poller<T> {
*
* @param callable a {@link Callable} to use to retrieve a result
* @return a future which itself can be used to get the result
* @throws java.lang.Exception
* @throws java.lang.Exception allows for checked exceptions
*/
Future<T> poll(Callable<T> callable) throws Exception;

View File

@@ -47,7 +47,7 @@ public class RepeatOperationsInterceptor implements MethodInterceptor {
/**
* Setter for the {@link RepeatOperations}.
*
* @param batchTempate
* @param batchTempate template to be used
* @throws IllegalArgumentException if the argument is null.
*/
public void setRepeatOperations(RepeatOperations batchTempate) {