RESOLVED - issue BATCH-466: Allow configurable ordering of Step/JobListeners

This commit is contained in:
dsyer
2008-05-29 14:10:51 +00:00
parent 56ddba0a7b
commit 8e25342701
9 changed files with 307 additions and 77 deletions

View File

@@ -15,12 +15,10 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.ChunkListener;
import org.springframework.core.Ordered;
/**
* @author Lucas Ward
@@ -28,7 +26,7 @@ import org.springframework.batch.core.ChunkListener;
*/
public class CompositeChunkListener implements ChunkListener {
private List listeners = new ArrayList();
private OrderedComposite listeners = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -36,7 +34,7 @@ public class CompositeChunkListener implements ChunkListener {
* @param listeners
*/
public void setListeners(ChunkListener[] listeners) {
this.listeners = Arrays.asList(listeners);
this.listeners.setItems(listeners);
}
/**
@@ -45,13 +43,14 @@ public class CompositeChunkListener implements ChunkListener {
* @param chunkListener
*/
public void register(ChunkListener chunkListener) {
if (!listeners.contains(chunkListener)) {
listeners.add(chunkListener);
}
listeners.add(chunkListener);
}
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.ChunkListener#afterChunk()
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
*
* @see org.springframework.batch.core.ChunkListener#afterChunk()
*/
public void afterChunk() {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
@@ -60,11 +59,13 @@ public class CompositeChunkListener implements ChunkListener {
}
}
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.ChunkListener#beforeChunk()
/**
* Call the registered listeners in reverse order.
*
* @see org.springframework.batch.core.ChunkListener#beforeChunk()
*/
public void beforeChunk() {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
ChunkListener listener = (ChunkListener) iterator.next();
listener.beforeChunk();
}

View File

@@ -15,13 +15,11 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.core.Ordered;
/**
* @author Dave Syer
@@ -29,7 +27,7 @@ import org.springframework.batch.core.JobExecutionListener;
*/
public class CompositeExecutionJobListener implements JobExecutionListener {
private List listeners = new ArrayList();
private OrderedComposite listeners = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -37,7 +35,7 @@ public class CompositeExecutionJobListener implements JobExecutionListener {
* @param listeners
*/
public void setListeners(JobExecutionListener[] listeners) {
this.listeners = Arrays.asList(listeners);
this.listeners.setItems(listeners);
}
/**
@@ -46,38 +44,57 @@ public class CompositeExecutionJobListener implements JobExecutionListener {
* @param jobExecutionListener
*/
public void register(JobExecutionListener jobExecutionListener) {
if (!listeners.contains(jobExecutionListener)) {
listeners.add(jobExecutionListener);
}
listeners.add(jobExecutionListener);
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.JobExecutionListener#afterJob(org.springframework.batch.core.JobExecution)
*/
public void afterJob(JobExecution jobExecution) {
for (Iterator iterator = listeners.listIterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
JobExecutionListener listener = (JobExecutionListener) iterator.next();
listener.afterJob(jobExecution);
}
}
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.JobExecutionListener#beforeJob(org.springframework.batch.core.JobExecution)
*/
public void beforeJob(JobExecution jobExecution) {
for (Iterator iterator = listeners.listIterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
JobExecutionListener listener = (JobExecutionListener) iterator.next();
listener.beforeJob(jobExecution);
}
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.JobExecutionListener#onError(org.springframework.batch.core.JobExecution,
* java.lang.Throwable)
*/
public void onError(JobExecution jobExecution, Throwable e) {
for (Iterator iterator = listeners.listIterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
JobExecutionListener listener = (JobExecutionListener) iterator.next();
listener.onError(jobExecution, e);
}
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.JobExecutionListener#onInterrupt(org.springframework.batch.core.JobExecution)
*/
public void onInterrupt(JobExecution jobExecution) {
for (Iterator iterator = listeners.listIterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
JobExecutionListener listener = (JobExecutionListener) iterator.next();
listener.onInterrupt(jobExecution);
}
}
}

View File

@@ -15,20 +15,19 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.ItemReadListener;
import org.springframework.core.Ordered;
/**
* @author Lucas Ward
* @author Dave Syer
*
*/
public class CompositeItemReadListener implements ItemReadListener {
private List listeners = new ArrayList();
private OrderedComposite listeners = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -36,7 +35,7 @@ public class CompositeItemReadListener implements ItemReadListener {
* @param itemReadListeners
*/
public void setListeners(ItemReadListener[] itemReadListeners) {
this.listeners = Arrays.asList(itemReadListeners);
this.listeners.setItems(itemReadListeners);
}
/**
@@ -45,18 +44,26 @@ public class CompositeItemReadListener implements ItemReadListener {
* @param itemReaderListener
*/
public void register(ItemReadListener itemReaderListener) {
if (!listeners.contains(itemReaderListener)) {
listeners.add(itemReaderListener);
}
listeners.add(itemReaderListener);
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemReadListener#afterRead(java.lang.Object)
*/
public void afterRead(Object item) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
ItemReadListener listener = (ItemReadListener) iterator.next();
listener.afterRead(item);
}
}
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemReadListener#beforeRead()
*/
public void beforeRead() {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
ItemReadListener listener = (ItemReadListener) iterator.next();
@@ -64,6 +71,11 @@ public class CompositeItemReadListener implements ItemReadListener {
}
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemReadListener#onReadError(java.lang.Exception)
*/
public void onReadError(Exception ex) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
ItemReadListener listener = (ItemReadListener) iterator.next();

View File

@@ -15,20 +15,19 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.ItemWriteListener;
import org.springframework.core.Ordered;
/**
* @author Lucas Ward
* @author Dave Syer
*
*/
public class CompositeItemWriteListener implements ItemWriteListener {
private List listeners = new ArrayList();
private OrderedComposite listeners = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -36,7 +35,7 @@ public class CompositeItemWriteListener implements ItemWriteListener {
* @param itemWriteListeners
*/
public void setListeners(ItemWriteListener[] itemWriteListeners) {
this.listeners = Arrays.asList(itemWriteListeners);
this.listeners.setItems(itemWriteListeners);
}
/**
@@ -45,18 +44,26 @@ public class CompositeItemWriteListener implements ItemWriteListener {
* @param itemReaderListener
*/
public void register(ItemWriteListener itemReaderListener) {
if (!listeners.contains(itemReaderListener)) {
listeners.add(itemReaderListener);
}
listeners.add(itemReaderListener);
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemWriteListener#afterWrite(java.lang.Object)
*/
public void afterWrite(Object item) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
ItemWriteListener listener = (ItemWriteListener) iterator.next();
listener.afterWrite(item);
}
}
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemWriteListener#beforeWrite(java.lang.Object)
*/
public void beforeWrite(Object item) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
ItemWriteListener listener = (ItemWriteListener) iterator.next();
@@ -64,8 +71,14 @@ public class CompositeItemWriteListener implements ItemWriteListener {
}
}
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.ItemWriteListener#onWriteError(java.lang.Exception,
* java.lang.Object)
*/
public void onWriteError(Exception ex, Object item) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = listeners.reverse(); iterator.hasNext();) {
ItemWriteListener listener = (ItemWriteListener) iterator.next();
listener.onWriteError(ex, item);
}

View File

@@ -15,12 +15,10 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.SkipListener;
import org.springframework.core.Ordered;
/**
* @author Dave Syer
@@ -28,7 +26,7 @@ import org.springframework.batch.core.SkipListener;
*/
public class CompositeSkipListener implements SkipListener {
private List listeners = new ArrayList();
private OrderedComposite listeners = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -36,7 +34,7 @@ public class CompositeSkipListener implements SkipListener {
* @param listeners
*/
public void setListeners(SkipListener[] listeners) {
this.listeners = Arrays.asList(listeners);
this.listeners.setItems(listeners);
}
/**
@@ -45,12 +43,12 @@ public class CompositeSkipListener implements SkipListener {
* @param listener
*/
public void register(SkipListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
listeners.add(listener);
}
/* (non-Javadoc)
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.SkipListener#onSkipInRead(java.lang.Throwable)
*/
public void onSkipInRead(Throwable t) {
@@ -60,8 +58,11 @@ public class CompositeSkipListener implements SkipListener {
}
}
/* (non-Javadoc)
* @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object, java.lang.Throwable)
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object,
* java.lang.Throwable)
*/
public void onSkipInWrite(Object item, Throwable t) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {

View File

@@ -15,14 +15,12 @@
*/
package org.springframework.batch.core.listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.core.Ordered;
/**
* @author Lucas Ward
@@ -31,7 +29,7 @@ import org.springframework.batch.repeat.ExitStatus;
*/
public class CompositeStepExecutionListener implements StepExecutionListener {
private List listeners = new ArrayList();
private OrderedComposite list = new OrderedComposite();
/**
* Public setter for the listeners.
@@ -39,7 +37,7 @@ public class CompositeStepExecutionListener implements StepExecutionListener {
* @param listeners
*/
public void setListeners(StepExecutionListener[] listeners) {
this.listeners = Arrays.asList(listeners);
list.setItems(listeners);
}
/**
@@ -48,43 +46,48 @@ public class CompositeStepExecutionListener implements StepExecutionListener {
* @param stepExecutionListener
*/
public void register(StepExecutionListener stepExecutionListener) {
if (!listeners.contains(stepExecutionListener)) {
listeners.add(stepExecutionListener);
}
list.add(stepExecutionListener);
}
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.StepListener#close()
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.StepExecutionListener#afterStep(StepExecution)
*/
public ExitStatus afterStep(StepExecution stepExecution) {
ExitStatus status = null;
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = list.reverse(); iterator.hasNext();) {
StepExecutionListener listener = (StepExecutionListener) iterator.next();
ExitStatus close = listener.afterStep(stepExecution);
status = status!=null ? status.and(close): close;
status = status != null ? status.and(close) : close;
}
return status;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.StepListener#open(org.springframework.batch.core.domain.JobParameters)
/**
* Call the registered listeners in order, respecting and prioritising those
* that implement {@link Ordered}.
* @see org.springframework.batch.core.StepExecutionListener#beforeStep(StepExecution)
*/
public void beforeStep(StepExecution stepExecution) {
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
StepExecutionListener listener = (StepExecutionListener) iterator.next();
listener.beforeStep(stepExecution);
}
}
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.StepListener#onError(java.lang.Throwable)
/**
* Call the registered listeners in reverse order, respecting and
* prioritising those that implement {@link Ordered}.
* @see org.springframework.batch.core.StepExecutionListener#onErrorInStep(StepExecution,
* java.lang.Throwable)
*/
public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) {
ExitStatus status = null;
for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
for (Iterator iterator = list.reverse(); iterator.hasNext();) {
StepExecutionListener listener = (StepExecutionListener) iterator.next();
ExitStatus close = listener.onErrorInStep(stepExecution, e);
status = status!=null ? status.and(close): close;
status = status != null ? status.and(close) : close;
}
return status;
}

View File

@@ -0,0 +1,94 @@
/*
* 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.core.listener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
/**
* @author Dave Syer
*
*/
class OrderedComposite {
private List unordered = new ArrayList();
private Collection ordered = new TreeSet(new OrderComparator());
private List list = new ArrayList();
/**
* Public setter for the listeners.
*
* @param items
*/
public void setItems(Object[] items) {
unordered.clear();
ordered.clear();
for (int i = 0; i < items.length; i++) {
add(items[i]);
}
}
/**
* Register additional item.
*
* @param item
*/
public void add(Object item) {
if (item instanceof Ordered) {
if (!ordered.contains(item)) {
ordered.add(item);
}
}
else {
if (!unordered.contains(item)) {
unordered.add(item);
}
}
list.clear();
list.addAll(ordered);
list.addAll(unordered);
}
/**
* Public getter for the list of items. The {@link Ordered} items come
* first, followed by any unordered ones.
* @return an iterator over the list of items
*/
public Iterator iterator() {
return new ArrayList(list).iterator();
}
/**
* Public getter for the list of items in reverse. The {@link Ordered} items come
* last, after any unordered ones.
* @return an iterator over the list of items
*/
public Iterator reverse() {
ArrayList result = new ArrayList(list);
Collections.reverse(result);
return result.iterator();
}
}

View File

@@ -164,7 +164,7 @@ public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAw
Assert.notNull(getItemReader(), "ItemReader must be provided");
Assert.notNull(getItemWriter(), "ItemWriter must be provided");
Assert.notNull(transactionManager, "TransactionManager must be provided");
jobRepositoryValidator .validate(jobRepository);
jobRepositoryValidator.validate(jobRepository);
step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
step.setTransactionManager(transactionManager);