RESOLVED - issue BATCH-88: StatisticsProvider is a leaky abstraction

http://jira.springframework.org/browse/BATCH-88
This commit is contained in:
dsyer
2008-01-24 16:22:56 +00:00
parent d8f2ccb354
commit 00ca5ce850
29 changed files with 522 additions and 866 deletions

View File

@@ -11,14 +11,13 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
/**
* Runs a collection of ItemProcessors in fixed-order sequence.
*
* @author Robert Kasanicky
*/
public class CompositeItemProcessor implements ItemProcessor, Restartable, StatisticsProvider {
public class CompositeItemProcessor implements ItemProcessor, Restartable {
private static final String SEPARATOR = "#";
@@ -72,23 +71,6 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
}
/**
* @return Properties containing statistics of all injected ItemProcessors,
* property keys are prefixed with the list index of the ItemProcessor.
*/
public Properties getStatistics() {
return createCompoundProperties(new PropertiesExtractor() {
public Properties extractProperties(Object o) {
if (o instanceof StatisticsProvider) {
return ((StatisticsProvider) o).getStatistics();
}
else {
return null;
}
}
});
}
public void setItemProcessors(List itemProcessors) {
this.itemProcessors = itemProcessors;
}

View File

@@ -8,24 +8,23 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.restart.GenericRestartData;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Simple wrapper around {@link ItemWriter} providing {@link Restartable} and
* {@link StatisticsProvider} where the {@link ItemWriter} does.
* Simple wrapper around {@link ItemWriter} providing {@link Restartable} where
* the {@link ItemWriter} does. To make sure
*
* @author Dave Syer
* @author Robert Kasanicky
*/
public class ItemWriterItemProcessor implements ItemProcessor, Restartable, Skippable,
StatisticsProvider, InitializingBean {
public class ItemWriterItemProcessor implements ItemProcessor, Restartable, Skippable, InitializingBean {
private ItemWriter writer;
/**
* Calls {@link #doProcess(Object)} and then writes the result to the {@link ItemWriter}.
* Calls {@link #doProcess(Object)} and then writes the result to the
* {@link ItemWriter}.
*
* @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object)
*/
@@ -35,8 +34,8 @@ public class ItemWriterItemProcessor implements ItemProcessor, Restartable, Skip
}
/**
* By default returns the argument. This method is an extension point
* meant to be overridden by subclasses that implement processing logic.
* By default returns the argument. This method is an extension point meant
* to be overridden by subclasses that implement processing logic.
*/
protected Object doProcess(Object item) throws Exception {
return item;
@@ -53,13 +52,13 @@ public class ItemWriterItemProcessor implements ItemProcessor, Restartable, Skip
* @see Restartable#getRestartData()
*/
public RestartData getRestartData() {
Assert.state(writer != null, "Source must not be null.");
if (writer instanceof Restartable) {
return ((Restartable) writer).getRestartData();
}
else{
else {
return new GenericRestartData(new Properties());
}
}
@@ -68,35 +67,21 @@ public class ItemWriterItemProcessor implements ItemProcessor, Restartable, Skip
* @see Restartable#restoreFrom(RestartData)
*/
public void restoreFrom(RestartData data) {
Assert.state(writer != null, "Source must not be null.");
if (writer instanceof Restartable) {
((Restartable) writer).restoreFrom(data);
}
}
/**
* @return delegates to the parent template of it is a
* {@link StatisticsProvider}, otherwise returns an empty
* {@link Properties} instance.
* @see StatisticsProvider#getStatistics()
*/
public Properties getStatistics() {
if (!(writer instanceof StatisticsProvider)) {
return new Properties();
}
return ((StatisticsProvider) writer).getStatistics();
}
public void skip() {
if (writer instanceof Skippable) {
((Skippable)writer).skip();
((Skippable) writer).skip();
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(writer);
}

View File

@@ -16,13 +16,10 @@
package org.springframework.batch.item.reader;
import java.util.Properties;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.restart.RestartData;
import org.springframework.batch.restart.Restartable;
import org.springframework.batch.statistics.StatisticsProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -33,7 +30,7 @@ import org.springframework.util.Assert;
*
* @author Dave Syer
*/
public class DelegatingItemReader extends AbstractItemReader implements Restartable, StatisticsProvider, Skippable, InitializingBean{
public class DelegatingItemReader extends AbstractItemReader implements Restartable, Skippable, InitializingBean{
private ItemReader inputSource;
@@ -73,19 +70,6 @@ public class DelegatingItemReader extends AbstractItemReader implements Restarta
((Restartable) inputSource).restoreFrom(data);
}
/**
* @return delegates to the parent template of it is a
* {@link StatisticsProvider}, otherwise returns an empty
* {@link Properties} instance.
* @see StatisticsProvider#getStatistics()
*/
public Properties getStatistics() {
if (!(inputSource instanceof StatisticsProvider)) {
return new Properties();
}
return ((StatisticsProvider) inputSource).getStatistics();
}
/**
* Setter for input source.
* @param source

View File

@@ -0,0 +1,89 @@
/*
* 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.statistics;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Simple {@link StatisticsService} that makes no attempt to aggregate or
* resolve conflicts between key names. All the contributions registered are
* simply polled and added "as is" to the aggregate properties.
*
* @author Dave Syer
*
*/
public class SimpleStatisticsService implements StatisticsService {
private Map registry = new HashMap();
/**
* Simple aggregate statistics provider for the contributions registered
* under the given key.
*
* @see org.springframework.batch.statistics.StatisticsService#getStatistics(java.lang.Object)
*/
public Properties getStatistics(Object key) {
Set set = new LinkedHashSet();
synchronized (registry) {
Collection collection = (Collection) registry.get(key);
if (collection != null) {
set = new LinkedHashSet(collection);
}
}
return aggregate(set);
}
/**
* @param list a list of {@link StatisticsProvider}s
* @return aggregated statistics
*/
private Properties aggregate(Collection list) {
Properties result = new Properties();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
StatisticsProvider provider = (StatisticsProvider) iterator.next();
Properties properties = provider.getStatistics();
if (properties != null) {
result.putAll(properties);
}
}
return result;
}
/**
* Register a {@link StatisticsProvider} as one of the interesting providers
* under the provided key.
*
* @see org.springframework.batch.statistics.StatisticsService#register(java.lang.Object,
* org.springframework.batch.statistics.StatisticsProvider)
*/
public void register(Object key, StatisticsProvider provider) {
synchronized (registry) {
Set set = (Set) registry.get(key);
if (set == null) {
set = new LinkedHashSet();
registry.put(key, set);
}
set.add(provider);
}
}
}

View File

@@ -20,7 +20,7 @@ import java.util.Properties;
/**
* Provides statistics for a given module run. Any class that implements
* this interface is garunteeing that it will provide Statistics.
* this interface is guaranteeing that it will provide Statistics.
*
* @author Lucas Ward
*

View File

@@ -0,0 +1,50 @@
/*
* 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.statistics;
import java.util.Properties;
/**
* Generalised statistics aggregation strategy. Clients register
* {@link StatisticsProvider} instances under a well-known key, and then when
* they ask for statistics by that key, they receive an aggregate of all the
* values given by registered providers.
*
* @author Dave Syer
*
*/
public interface StatisticsService {
/**
* Register the {@link StatisticsProvider} instance as one of possibly
* several that are associated with the given key.
*
* @param key the key under which to add the provider
* @param provider a {@link StatisticsProvider}
*/
void register(Object key, StatisticsProvider provider);
/**
* Extract and aggregate the statistics from all providers under this key.
*
* @param key the key under which {@link StatisticsProvider} instances might
* have been registered.
* @return {@link Properties} summarising the statistics of all providers
* registered under this key, or empty otherwise.
*/
Properties getStatistics(Object key);
}