class AbstractPaginatedDataItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> {

	protected volatile int page = 0;

	protected int pageSize = 10;

	protected Iterator<T> results;

	private final Lock lock = new ReentrantLock();

	/**
	 * The number of items to be read with each page.
	 * @param pageSize the number of items. pageSize must be greater than zero.
	 */
	public void setPageSize(int pageSize) {
		Assert.isTrue(pageSize > 0, "pageSize must be greater than zero");
		this.pageSize = pageSize;
	}

	@Nullable
	@Override
	protected T doRead() throws Exception {<FILL_FUNCTION_BODY>}

	/**
	 * Method this {@link ItemStreamReader} delegates to for the actual work of reading a
	 * page. Each time this method is called, the resulting {@link Iterator} should
	 * contain the items read within the next page. <br>
	 * <br>
	 * If the {@link Iterator} is empty or null when it is returned, this
	 * {@link ItemReader} will assume that the input has been exhausted.
	 * @return an {@link Iterator} containing the items within a page.
	 */
	protected abstract Iterator<T> doPageRead();

	@Override
	protected void doOpen() throws Exception {
	}

	@Override
	protected void doClose() throws Exception {
	}

	@Override
	protected void jumpToItem(int itemLastIndex) throws Exception {
		this.lock.lock();
		try {
			page = itemLastIndex / pageSize;
			int current = itemLastIndex % pageSize;

			Iterator<T> initialPage = doPageRead();

			for (; current >= 0; current--) {
				initialPage.next();
			}
		}
		finally {
			this.lock.unlock();
		}
	}

}


		this.lock.lock();
		try {
			if (results == null || !results.hasNext()) {

				results = doPageRead();

				page++;

				if (results == null || !results.hasNext()) {
					return null;
				}
			}

			if (results.hasNext()) {
				return results.next();
			}
			else {
				return null;
			}
		}
		finally {
			this.lock.unlock();
		}
	
<methods>public non-sealed void <init>() ,public void close() throws org.springframework.batch.item.ItemStreamException,public int getCurrentItemCount() ,public boolean isSaveState() ,public void open(org.springframework.batch.item.ExecutionContext) throws org.springframework.batch.item.ItemStreamException,public T read() throws java.lang.Exception,public void setCurrentItemCount(int) ,public void setMaxItemCount(int) ,public void setSaveState(boolean) ,public void update(org.springframework.batch.item.ExecutionContext) throws org.springframework.batch.item.ItemStreamException<variables>private static final java.lang.String READ_COUNT,private static final java.lang.String READ_COUNT_MAX,private int currentItemCount,private int maxItemCount,private boolean saveState