OPEN - issue BATCH-385: Merge user attributes in StepContext with ExecutionContext

http://jira.springframework.org/browse/BATCH-385

Remove step scope support.
This commit is contained in:
dsyer
2008-02-29 12:22:48 +00:00
parent ecf28bd588
commit 90c8f71173
36 changed files with 104 additions and 1438 deletions

View File

@@ -31,9 +31,6 @@ import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
import org.springframework.batch.execution.listener.CompositeJobListener;
import org.springframework.batch.execution.scope.SimpleStepContext;
import org.springframework.batch.execution.scope.StepContext;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
@@ -87,7 +84,7 @@ public class SimpleJob extends AbstractJob {
execution.setStartTime(new Date());
updateStatus(execution, BatchStatus.STARTING);
listener.beforeJob(execution);
int startedCount = 0;
@@ -103,15 +100,7 @@ public class SimpleJob extends AbstractJob {
updateStatus(execution, BatchStatus.STARTED);
StepExecution stepExecution = execution.createStepExecution(step);
StepContext parentStepContext = StepSynchronizationManager.getContext();
final StepContext stepContext = new SimpleStepContext(stepExecution, parentStepContext);
StepSynchronizationManager.register(stepContext);
try {
step.execute(stepExecution);
} finally {
// clear any registered synchronizations
StepSynchronizationManager.close();
}
step.execute(stepExecution);
status = stepExecution.getExitStatus();
@@ -190,8 +179,8 @@ public class SimpleJob extends AbstractJob {
}
else {
// start max has been exceeded, throw an exception.
throw new BatchCriticalException("Maximum start limit exceeded for step: " + step.getName()
+ "StartMax: " + step.getStartLimit());
throw new BatchCriticalException("Maximum start limit exceeded for step: " + step.getName() + "StartMax: "
+ step.getStartLimit());
}
}

View File

@@ -21,7 +21,6 @@ import java.util.Iterator;
import java.util.List;
import org.springframework.batch.core.domain.ChunkListener;
import org.springframework.batch.core.domain.ItemReadListener;
import org.springframework.batch.core.domain.ItemWriteListener;
/**

View File

@@ -1,39 +0,0 @@
/*
* 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.execution.scope;
import org.springframework.batch.core.domain.JobParameters;
/**
* Marker interface for callback injecting {@link JobParameters}. A Spring bean
* which is step scoped will be injected with the {@link JobParameters} when it
* is instantiated. In most cases this will require the use of
* <aop:scoped-proxy> when the bean is used as a dependency in a
* singleton.
*
* @author Dave Syer
*
*/
public interface JobParametersAware {
/**
* Callback method for injection of {@link JobParameters}.
*
* @param jobParameters the {@link JobParameters} to set.
*/
void setJobParameters(JobParameters jobParameters);
}

View File

@@ -1,173 +0,0 @@
/*
* 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.execution.scope;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor;
/**
* Simple implementation of {@link StepContext}.
*
* @author Dave Syer
*
*/
public class SimpleStepContext extends SynchronizedAttributeAccessor implements StepContext {
private Map callbacks = new HashMap();
private StepContext parent;
private StepExecution stepExecution;
/**
* Default constructor.
*/
public SimpleStepContext(StepExecution stepExecution) {
this(stepExecution, null);
}
/**
* @param object
*/
public SimpleStepContext(StepExecution stepExecution, StepContext parent) {
super();
this.parent = parent;
this.stepExecution = stepExecution;
}
/*
* (non-Javadoc)
* @see org.springframework.batch.repeat.context.SynchronizedAttributeAccessor#setAttribute(java.lang.String,
* java.lang.Object)
*/
public void setAttribute(String name, Object value) {
super.setAttribute(name, value);
}
/*
* (non-Javadoc)
*
* @see org.springframework.batch.execution.scope.StepContext#getParent()
*/
public StepContext getParent() {
return parent;
}
/*
* (non-Javadoc)
*
* @see org.springframework.batch.repeat.RepeatContext#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
/*
* (non-Javadoc)
*
* @see org.springframework.batch.execution.scope.StepContext#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback) {
synchronized (callbacks) {
Set set = (Set) callbacks.get(name);
if (set == null) {
set = new HashSet();
callbacks.put(name, set);
}
set.add(callback);
}
}
/*
* (non-Javadoc)
* @see org.springframework.batch.execution.scope.StepContext#close()
*/
public void close() {
List errors = new ArrayList();
Set copy;
synchronized (callbacks) {
copy = new HashSet(callbacks.entrySet());
}
for (Iterator iter = copy.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
Set set = (Set) entry.getValue();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Runnable callback = (Runnable) iterator.next();
/*
* There used to be a check here to make sure there was an
* attribute with the given name, but an inner bean is not
* registered with the bean factory, so the destroy method is
* only called in inner bean if we make the callback
* unconditionally.
*/
if (callback != null) {
/*
* The documentation of the interface says that these
* callbacks must not throw exceptions, but we don't trust
* them necessarily...
*/
try {
callback.run();
}
catch (RuntimeException t) {
errors.add(t);
}
}
}
}
if (errors.isEmpty()) {
return;
}
Exception error = (Exception) errors.get(0);
if (error instanceof RuntimeException) {
throw (RuntimeException) error;
}
else {
throw new BatchCriticalException("Could not close step context, rethrowing first of " + errors.size()
+ " execptions.", error);
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.batch.execution.scope.StepContext#getJobIdentifier()
*/
public StepExecution getStepExecution() {
return stepExecution;
}
/* (non-Javadoc)
* @see org.springframework.batch.execution.scope.StepContext#getIdentifier()
*/
public String getIdentifier() {
return "JOB_EXECUTION_ID:"+stepExecution.getJobExecutionId();
}
}

View File

@@ -1,70 +0,0 @@
/*
* 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.execution.scope;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.core.AttributeAccessor;
/**
* Interface for step-scoped context object and step-scoped services. This
* interface extends {@link AttributeAccessor}, so there is an underlying map
* that can be used for storing state during a step execution. The storage is
* <em>volatile</em>: the attributes are not persisted and not durable across
* steps in a job, or across restarts of a failed job.
*
* @see ExecutionContext for access to durable attributes that will be restored
* in the case of a restart.
*
* @author Dave Syer
*
*/
public interface StepContext extends AttributeAccessor {
/**
* Accessor for the {@link StepExecution} associated with the currently
* executing step.
*
* @return the {@link StepExecution} associated with the current step
*/
StepExecution getStepExecution();
/**
* Accessor for the parent context.
*
* @return the parent of this context (or null if there isn't one)
*/
StepContext getParent();
/**
* Register a destruction callback for the end of life of the scope.
*/
void registerDestructionCallback(String name, Runnable callback);
/**
* Clean up any resources held during the context of the step.
*/
void close();
/**
* Identify this context so that concurrently running jobs in the same VM
* can be distinguished.
*
* @return a sufficiently unique identifier for this context
*/
String getIdentifier();
}

View File

@@ -1,38 +0,0 @@
/*
* 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.execution.scope;
/**
* Marker interface for beans to be injected with a {@link StepContext}. Useful
* for business logic implementations that want to store some state in the
* context, to communicate between iterations, or with an enclosing executor.<br/>
*
* A bean which is step scoped which also implements this interface will be
* injected with the context at the start of the bean lifecycle.
*
* @author Dave Syer
*
*/
public interface StepContextAware {
/**
* Callback for injection of {@link StepContext}.
*
* @param context
* the current context supplied by framework.
*/
void setStepContext(StepContext context);
}

View File

@@ -1,158 +0,0 @@
/*
* 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.execution.scope;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.core.Ordered;
/**
* Scope for step context. Objects in this scope with &lt;aop:scoped-proxy/&gt;
* use the Spring container as an object factory, so there is only one instance
* of such a bean per executing step.
*
* @author Dave Syer
*
*/
public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
private int order = Ordered.LOWEST_PRECEDENCE;
private Object mutex = new Object();
/**
* @param order the order value to set priority of callback execution for
* the {@link BeanFactoryPostProcessor} part of this scope bean.
*/
public void setOrder(int order) {
this.order = order;
}
/*
* (non-Javadoc)
* @see org.springframework.core.Ordered#getOrder()
*/
public int getOrder() {
return order;
}
private String name = "step";
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
* org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory objectFactory) {
StepContext context = getContext();
Object scopedObject = context.getAttribute(name);
if (scopedObject == null) {
synchronized (mutex) {
scopedObject = context.getAttribute(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
if (scopedObject instanceof StepContextAware) {
((StepContextAware) scopedObject).setStepContext(context);
}
if (scopedObject instanceof JobParametersAware) {
try {
JobParameters jobParameters = context.getStepExecution().getJobExecution().getJobInstance()
.getJobParameters();
((JobParametersAware) scopedObject).setJobParameters(jobParameters);
}
catch (NullPointerException e) {
// ignore
}
}
context.setAttribute(name, scopedObject);
}
}
}
return scopedObject;
}
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId() {
StepContext context = getContext();
return context.getIdentifier();
}
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback) {
StepContext context = getContext();
context.registerDestructionCallback(name, callback);
}
/*
* (non-Javadoc)
*
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name) {
StepContext context = getContext();
return context.removeAttribute(name);
}
/**
* Get an attribute accessor in the form of a {@link SimpleStepContext} that
* can be used to store scoped bean instances.
*
* @return the current step context which we can use as a scope storage
* medium
*/
private StepContext getContext() {
StepContext context = StepSynchronizationManager.getContext();
if (context == null) {
throw new IllegalStateException("No context holder available for step scope");
}
return context;
}
/**
* Register this scope with the enclosing BeanFactory.
*
* @param beanFactory the BeanFactory to register with
* @throws BeansException if there is a problem.
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerScope(name, this);
}
/**
* Public setter for the name property. This can then be used as a bean
* definition attribute, e.g. scope="step". Defaults to "step".
*
* @param name the name to set for this scope.
*/
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,76 +0,0 @@
/*
* 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.execution.scope;
/**
* @author Dave Syer
*
*/
public class StepSynchronizationManager {
private static final ThreadLocal contextHolder = new InheritableThreadLocal();
/**
* Getter for the current context..
*
* @return the current {@link StepContext} or null if there is none
* (if we are not in a step).
*/
public static StepContext getContext() {
return (StepContext) contextHolder.get();
}
/**
* Method for registering a context - should only be used by
* {@link StepExecutor} implementations to ensure that {@link #getContext()}
* always returns the correct value.
* @param context the step context to register
*/
public static void register(StepContext context) {
StepSynchronizationManager.contextHolder.set(context);
}
/**
* Method for de-registering the current context - should only be used by
* {@link StepExecutor} implementations to ensure that {@link #getContext()}
* always returns the correct value.
*
* @return the old value if there was one.
*/
public static StepContext close() {
StepContext oldSession = getContext();
if (oldSession == null) {
return null;
}
oldSession.close();
StepContext context = oldSession.getParent();
StepSynchronizationManager.contextHolder.set(context);
return context;
}
/**
* Used internally by {@link StepExecutor} implementations to clear the
* current context at the end of a batch.
*
* @return the old value if there was one.
*/
public static StepContext clear() {
StepContext context = getContext();
StepSynchronizationManager.contextHolder.set(null);
return context;
}
}

View File

@@ -1,7 +0,0 @@
<html>
<body>
<p>
Specific implementations of scope concerns.
</p>
</body>
</html>

View File

@@ -38,7 +38,6 @@ import org.springframework.batch.execution.repository.dao.MapJobExecutionDao;
import org.springframework.batch.execution.repository.dao.MapJobInstanceDao;
import org.springframework.batch.execution.repository.dao.MapStepExecutionDao;
import org.springframework.batch.execution.repository.dao.StepExecutionDao;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.step.AbstractStep;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.item.reader.AbstractItemReader;
@@ -267,21 +266,6 @@ public class SimpleJobTests extends TestCase {
"JobInterruptedException"));
}
public void testStepContextInitialized() throws Exception {
stepConfiguration1.setCallback(new Runnable() {
public void run() {
assertNotNull(StepSynchronizationManager.getContext().getStepExecution());
list.add("asserted context");
};
});
job.execute(jobExecution);
assertEquals(2, list.size());
assertTrue(list.contains("asserted context"));
}
/*
* Check JobRepository to ensure status is being saved.
*/

View File

@@ -1,95 +0,0 @@
/*
* 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.execution.scope;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.core.domain.JobParameters;
import org.springframework.batch.execution.job.JobSupport;
import org.springframework.batch.execution.step.StepSupport;
import org.springframework.batch.repeat.synch.RepeatSynchronizationManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
/**
* @author Dave Syer
*
*/
public class JobParametersAwareStepScopeTests extends TestCase {
private StepScope scope = new StepScope();
private SimpleStepContext context;
JobParameters parameters = new JobParameters();
/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
JobExecution jobExecution = new JobExecution(new JobInstance(new Long(1L), parameters, new JobSupport()), new Long(11L));
context = new SimpleStepContext(jobExecution.createStepExecution(new StepSupport()));
StepSynchronizationManager.register(context);
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
RepeatSynchronizationManager.clear();
super.tearDown();
}
public void testInjection() throws Exception {
final TestBeanAware foo = new TestBeanAware();
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
assertEquals(foo, value);
assertTrue(context.hasAttribute("foo"));
assertEquals(parameters, foo.getJobParameters());
}
public void testFailedInjection() throws Exception {
// Null JobInstance so no parameters
context.getStepExecution().getJobExecution().setJobInstance(null);
final TestBeanAware foo = new TestBeanAware();
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
assertEquals(foo, value);
assertTrue(context.hasAttribute("foo"));
assertEquals(null, foo.getJobParameters());
}
public static class TestBeanAware implements JobParametersAware {
private JobParameters jobParameters;
public void setJobParameters(JobParameters jobParameters) {
this.jobParameters = jobParameters;
}
public JobParameters getJobParameters() {
return jobParameters;
}
}
}

View File

@@ -1,130 +0,0 @@
/*
* 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.execution.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.execution.step.StepSupport;
/**
* @author Dave Syer
*
*/
public class SimpleStepContextTests extends TestCase {
private SimpleStepContext context = new SimpleStepContext(null, new SimpleStepContext(null));
/**
* Test method for
* {@link org.springframework.batch.execution.scope.SimpleStepContext#StepScopeContext()}.
*/
public void testStepScopeContext() {
assertNull(new SimpleStepContext(null).getParent());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.SimpleStepContext#getParent()}.
*/
public void testGetParent() {
assertNotNull(context.getParent());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.SimpleStepContext#getStepExecution()}.
*/
public void testGetStepExecution() {
assertNull(context.getStepExecution());
context = new SimpleStepContext(new StepExecution(new StepSupport("stepName"), null, null));
assertNotNull(context.getStepExecution());
}
private List list = new ArrayList();
/**
* Test method for
* {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackSunnyDay() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.setAttribute("foo", "FOO");
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
context.close();
assertEquals(1, list.size());
assertEquals("bar", list.get(0));
}
/**
* Test method for
* {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackMissingAttribute() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
context.close();
// Yes the callback should be called even if the attribute is missing -
// for inner beans
assertEquals(1, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.repeat.context.SimpleStepContext#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testDestructionCallbackWithException() throws Exception {
SimpleStepContext context = new SimpleStepContext(null);
context.setAttribute("foo", "FOO");
context.setAttribute("bar", "BAR");
context.registerDestructionCallback("bar", new Runnable() {
public void run() {
list.add("spam");
throw new RuntimeException("fail!");
}
});
context.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
throw new RuntimeException("fail!");
}
});
try {
context.close();
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
// We don't care which one was thrown...
assertEquals("fail!", e.getMessage());
}
// ...but we do care that both were executed:
assertEquals(2, list.size());
assertTrue(list.contains("bar"));
assertTrue(list.contains("spam"));
}
}

View File

@@ -1,181 +0,0 @@
/*
* 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.execution.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.AttributeAccessor;
/**
* @author Dave Syer
*
*/
public class StepContextAwareStepScopeTests extends TestCase {
private static List list = new ArrayList();
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
StepSynchronizationManager.clear();
list.clear();
}
public void testScopedBean() throws Exception {
StepSynchronizationManager.register(new SimpleStepContext(null));
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBean bean = (TestBean) applicationContext.getBean("bean");
assertNotNull(bean);
assertEquals("foo", bean.name);
}
public void testScopedBeanWithDestroyCallback() throws Exception {
assertEquals(0, list.size());
StepSynchronizationManager.register(new SimpleStepContext(null));
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBean bean = (TestBean) applicationContext.getBean("bean");
assertNotNull(bean);
StepSynchronizationManager.close();
assertEquals(1, list.size());
}
public void testScopedBeanWithAware() throws Exception {
StepContext context = new SimpleStepContext(null);
StepSynchronizationManager.register(context);
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("aware");
assertNotNull(bean);
assertEquals("bar", bean.name);
assertEquals(context, bean.context);
}
public void testScopedBeanWithInner() throws Exception {
StepSynchronizationManager.register(new SimpleStepContext(null));
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"scope-tests.xml", getClass());
TestBean bean = ((TestBean) applicationContext.getBean("inner")).child;
assertNotNull(bean);
assertEquals("bar", bean.name);
StepSynchronizationManager.close();
assertEquals(1, list.size());
}
public void testScopedBeanWithProxy() throws Exception {
StepContext context = new SimpleStepContext(null);
StepSynchronizationManager.register(context);
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("proxy");
assertNotNull(bean);
// A scoped proxy is only accessible through public methods
assertEquals(null, bean.name);
assertEquals("spam", bean.getName());
assertEquals(context, bean.getContext());
}
public void testScopedBeanWithProxyInThread() throws Exception {
StepSynchronizationManager.register(new SimpleStepContext(null));
final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
new Thread(new Runnable() {
public void run() {
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("proxy");
list.add(bean.getName());
}
}).start();
int count = 0;
while(list.size()==0 && count++ <10) {
Thread.sleep(100);
}
if (list.size()==0) {
fail("Scoped proxy was not created in child thread - maybe we need to use InheritableThreadLocal?");
}
String name = (String) list.get(0);
assertEquals("spam", name);
}
public void testScopedBeanWithTwoProxiesInThreads() throws Exception {
StepSynchronizationManager.register(new SimpleStepContext(null));
final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope-tests.xml", getClass());
new Thread(new Runnable() {
public void run() {
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("proxy");
int count = 0;
while(list.size()==0 && count++ <10) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
fail("Timeout waiting for other thread to add a bean to list.");
}
}
bean.getName();
list.add(bean);
}
}).start();
new Thread(new Runnable() {
public void run() {
TestBeanAware bean = (TestBeanAware) applicationContext.getBean("proxy");
bean.getName();
list.add(bean);
}
}).start();
int count = 0;
while(list.size()<2 && count++ <10) {
Thread.sleep(100);
}
if (list.size()<2) {
fail("Scoped proxies were not created in child threads");
}
TestBeanAware bean1 = (TestBeanAware) list.get(0);
TestBeanAware bean2 = (TestBeanAware) list.get(1);
assertEquals("spam", bean1.getName());
assertSame(bean1.getLock(), bean2.getLock());
}
public static class TestBean {
String name;
TestBean child;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setChild(TestBean child) {
this.child = child;
}
public void close() {
list.add("close");
}
}
public static class TestBeanAware extends TestBean implements StepContextAware {
AttributeAccessor context;
Object lock = new Object();
public void setStepContext(StepContext context) {
this.context = context;
}
public AttributeAccessor getContext() {
return context;
}
public Object getLock() {
return lock;
}
}
}

View File

@@ -1,211 +0,0 @@
/*
* 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.execution.scope;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobInstance;
import org.springframework.batch.execution.job.JobSupport;
import org.springframework.batch.execution.step.StepSupport;
import org.springframework.batch.repeat.synch.RepeatSynchronizationManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.StaticApplicationContext;
/**
* @author Dave Syer
*
*/
public class StepScopeTests extends TestCase {
private StepScope scope = new StepScope();
private SimpleStepContext context;
/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
JobExecution jobExecution = new JobExecution(new JobInstance(new Long(1L), null, new JobSupport()), new Long(11L));
context = new SimpleStepContext(jobExecution.createStepExecution(new StepSupport()));
StepSynchronizationManager.register(context);
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
RepeatSynchronizationManager.clear();
super.tearDown();
}
public void testGetWithNoContext() throws Exception {
final String foo = "bar";
StepSynchronizationManager.clear();
try {
scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
// expected
}
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithNothingAlreadyThere() {
final String foo = "bar";
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return foo;
}
});
assertEquals(foo, value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithSomethingAlreadyThere() {
context.setAttribute("foo", "bar");
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return null;
}
});
assertEquals("bar", value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)}.
*/
public void testGetWithSomethingAlreadyInParentContext() {
StepContext context = new SimpleStepContext(null);
StepSynchronizationManager.register(context);
context.setAttribute("foo", "bar");
Object value = scope.get("foo", new ObjectFactory() {
public Object getObject() throws BeansException {
return null;
}
});
assertEquals("bar", value);
assertTrue(context.hasAttribute("foo"));
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#getConversationId()}.
*/
public void testGetConversationId() {
String id = scope.getConversationId();
assertNotNull(id);
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#getConversationId()}.
*/
public void testGetConversationIdFromAttribute() {
String id = scope.getConversationId();
assertEquals("JOB_EXECUTION_ID:11", id);
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testRegisterDestructionCallback() {
final List list = new ArrayList();
context.setAttribute("foo", "bar");
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("foo");
}
});
assertEquals(0, list.size());
// When the context is closed, provided the attribute exists the
// callback is called...
context.close();
assertEquals(1, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#registerDestructionCallback(java.lang.String, java.lang.Runnable)}.
*/
public void testRegisterAnotherDestructionCallback() {
final List list = new ArrayList();
context.setAttribute("foo", "bar");
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("foo");
}
});
scope.registerDestructionCallback("foo", new Runnable() {
public void run() {
list.add("bar");
}
});
assertEquals(0, list.size());
// When the context is closed, provided the attribute exists the
// callback is called...
context.close();
assertEquals(2, list.size());
}
/**
* Test method for
* {@link org.springframework.batch.execution.scope.StepScope#remove(java.lang.String)}.
*/
public void testRemove() {
context.setAttribute("foo", "bar");
scope.remove("foo");
assertFalse(context.hasAttribute("foo"));
}
public void testOrder() throws Exception {
assertEquals(Integer.MAX_VALUE, scope.getOrder());
scope.setOrder(11);
assertEquals(11, scope.getOrder());
}
public void testName() throws Exception {
scope.setName("foo");
StaticApplicationContext beanFactory = new StaticApplicationContext();
scope.postProcessBeanFactory(beanFactory.getDefaultListableBeanFactory());
String[] scopes = beanFactory.getDefaultListableBeanFactory().getRegisteredScopeNames();
assertEquals(1, scopes.length);
assertEquals("foo", scopes[0]);
}
}

View File

@@ -14,7 +14,6 @@ import org.springframework.batch.core.domain.StepExecution;
import org.springframework.batch.core.listener.StepListenerSupport;
import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.execution.job.JobSupport;
import org.springframework.batch.execution.scope.StepSynchronizationManager;
import org.springframework.batch.execution.step.support.JobRepositorySupport;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.repeat.ExitStatus;
@@ -63,6 +62,7 @@ public class TaskletStepTests extends TestCase {
public void testSuccessfulExecutionWithStepContext() throws Exception {
TaskletStep step = new TaskletStep(new StubTasklet(false, false, true), new JobRepositorySupport());
step.afterPropertiesSet();
step.execute(stepExecution);
assertNotNull(stepExecution.getStartTime());
assertEquals(ExitStatus.FINISHED, stepExecution.getExitStatus());
@@ -85,6 +85,7 @@ public class TaskletStepTests extends TestCase {
throw new RuntimeException("foo");
}
});
step.afterPropertiesSet();
try {
step.execute(stepExecution);
fail("Expected BatchCriticalException");
@@ -130,13 +131,15 @@ public class TaskletStepTests extends TestCase {
}
}
private class StubTasklet implements Tasklet{
private class StubTasklet extends StepListenerSupport implements Tasklet {
private final boolean exitFailure;
private final boolean throwException;
private final boolean assertStepContext;
private StepExecution stepExecution;
public StubTasklet(boolean exitFailure, boolean throwException) {
this(exitFailure, throwException, false);
@@ -158,11 +161,15 @@ public class TaskletStepTests extends TestCase {
}
if (assertStepContext) {
assertNotNull(StepSynchronizationManager.getContext());
assertNotNull(this.stepExecution);
}
return ExitStatus.FINISHED;
}
public void beforeStep(StepExecution stepExecution) {
this.stepExecution = stepExecution;
}
}

View File

@@ -12,9 +12,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="loopJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="taskletStep">

View File

@@ -11,9 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="beanWrapperMapperJob" parent="simpleJob">
<property name="steps">
<list>
@@ -122,9 +119,4 @@
class="org.springframework.batch.sample.domain.Person"
scope="prototype" />
<bean parent="customEditorConfigurer" />
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
</beans>

View File

@@ -9,9 +9,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope"/>
<bean parent="jobConfigurationRegistryBeanPostProcessor"/>
<bean id="compositeProcessorJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
@@ -40,9 +37,7 @@
<!-- INFRASTRUCTURE SETUP -->
<bean id="fileInputTemplate" class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
<bean id="fileInputTemplate" class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource" ref="fileLocator" />
<property name="lineTokenizer" ref="fixedFileDescriptor" />
<property name="fieldSetMapper" ref="fieldSetMapper" />
@@ -96,9 +91,4 @@
<bean id="fieldSetMapper" class="org.springframework.batch.sample.mapping.TradeFieldSetMapper" />
<bean parent="customEditorConfigurer"/>
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
</beans>

View File

@@ -11,9 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="fixedLengthImportJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
@@ -46,9 +43,7 @@
</bean>
<bean id="fileInputTemplate" parent="testInputTemplate"
autowire-candidate="false" scope="step">
<aop:scoped-proxy />
</bean>
autowire-candidate="false"/>
<bean id="fixedFileDescriptor"
class="org.springframework.batch.io.file.transform.FixedLengthTokenizer">

View File

@@ -11,9 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="footballJob" parent="simpleJob">
<property name="startLimit" value="100" />
<property name="steps">
@@ -65,9 +62,7 @@
</bean>
<bean id="playerFileItemReader"
class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource"
value="classpath:data/footballjob/input/${player.file.name}" />
<property name="lineTokenizer">
@@ -84,9 +79,7 @@
</bean>
<bean id="gameFileItemReader"
class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource"
value="classpath:data/footballjob/input/${games.file.name}" />
<property name="lineTokenizer">
@@ -103,9 +96,7 @@
</bean>
<bean id="playerSummarizationSource"
class="org.springframework.batch.io.cursor.JdbcCursorItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.cursor.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="mapper">
<bean

View File

@@ -13,9 +13,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="hibernateJob" parent="simpleJob">
<!-- set restartable=false so that this job can be used by more than one test -->
<property name="restartable" value="false" />
@@ -59,13 +56,9 @@
</bean>
<bean id="hibernateItemReader"
class="org.springframework.batch.io.cursor.HibernateCursorItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.cursor.HibernateCursorItemReader">
<property name="queryString" value="from CustomerCredit" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean parent="customEditorConfigurer" />
</beans>

View File

@@ -12,9 +12,6 @@
<description>Example for iBATIS integration.</description>
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="ibatisJob" parent="simpleJob">
<property name="steps">
@@ -25,9 +22,7 @@
class="org.springframework.batch.sample.item.writer.CustomerCreditIncreaseWriter">
<property name="customerCreditDao">
<bean
class="org.springframework.batch.sample.dao.IbatisCustomerCreditWriter"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.sample.dao.IbatisCustomerCreditWriter">
<property name="sqlMapClient"
ref="sqlMapClient" />
<property name="statementId"
@@ -41,9 +36,7 @@
</bean>
<bean id="ibatisItemReader"
class="org.springframework.batch.io.driving.IbatisDrivingQueryItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.driving.IbatisDrivingQueryItemReader">
<property name="detailsQueryId" value="getCustomerCreditById" />
<property name="sqlMapClient" ref="sqlMapClient" />
<property name="keyGenerator" ref="ibatisKeyGenerator" />
@@ -61,12 +54,4 @@
<property name="dataSource" ref="dataSource" />
</bean>
<bean parent="customEditorConfigurer" />
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
</beans>

View File

@@ -11,9 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope"/>
<bean parent="jobConfigurationRegistryBeanPostProcessor"/>
<bean id="jobLauncher" class="org.springframework.batch.execution.launch.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">

View File

@@ -8,9 +8,6 @@
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="multilineJob" parent="simpleJob">
<property name="steps">
@@ -24,9 +21,7 @@
</property>
<property name="itemWriter">
<bean
class="org.springframework.batch.io.file.FlatFileItemWriter"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemWriter">
<property name="resource"
value="file:target/test-outputs/20070122.testStream.multilineStep.txt" />
<property name="fieldSetUnmapper">
@@ -39,9 +34,7 @@
</bean>
<bean id="fileItemReader"
class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource"
value="classpath:data/multilineJob/input/20070122.teststream.multilineStep.txt" />
<property name="lineTokenizer" ref="fixedFileDescriptor" />
@@ -79,10 +72,4 @@
<property name="columns" value="1-12, 13-15, 16-20, 21-29" />
</bean>
<bean parent="customEditorConfigurer" />
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
</beans>

View File

@@ -9,9 +9,7 @@
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="fileInputTemplate"
class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource" ref="fileInputLocator" />
<property name="lineTokenizer" ref="orderFileDescriptor" />
<property name="fieldSetMapper">
@@ -24,9 +22,7 @@
class="org.springframework.batch.item.writer.ItemTransformerItemWriter">
<property name="delegate">
<bean
class="org.springframework.batch.io.file.FlatFileItemWriter"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemWriter">
<property name="resource" ref="fileOutputLocator" />
<property name="fieldSetUnmapper">
<bean

View File

@@ -12,9 +12,6 @@
<import resource="multilineOrderOutputDescriptors.xml" />
<import resource="multilineOrderIo.xml" />
<bean parent="stepScope"/>
<bean parent="jobConfigurationRegistryBeanPostProcessor"/>
<bean id="multilineOrderJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
@@ -143,6 +140,4 @@
<constructor-arg type="java.lang.String" value="target/test-outputs/20070122.teststream.multilineOrderStep.TEMP.txt" />
</bean>
<bean parent="customEditorConfigurer"/>
</beans>

View File

@@ -10,10 +10,7 @@
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="parallelJob" parent="simpleJob">
<property name="steps">
<list>

View File

@@ -11,10 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean parent="customEditorConfigurer" />
<bean id="restartSampleJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
@@ -50,9 +46,7 @@
</bean>
<bean id="fileItemReader"
class="org.springframework.batch.io.file.FlatFileItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource" ref="fileLocator" />
<property name="lineTokenizer" ref="fixedFileDescriptor" />
<property name="fieldSetMapper" ref="fieldSetMapper" />

View File

@@ -11,9 +11,6 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="retrySample" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
@@ -35,10 +32,9 @@
<property name="limit" value="10" />
</bean>
<bean id="itemGenerator" parent="testGenerator" scope="step" autowire-candidate="false">
<aop:scoped-proxy/>
</bean>
<bean id="itemGenerator" parent="testGenerator" autowire-candidate="false"/>
<bean id="itemWriter"
class="org.springframework.batch.sample.item.writer.RetrySampleItemWriter" />
</beans>

View File

@@ -13,9 +13,6 @@
<import resource="tradeJobIo.xml" />
<!--import resource="tradeJobAop.xml" /-->
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="tradeJob" parent="simpleJob">
<property name="steps">
<list>
@@ -56,9 +53,7 @@
</bean>
<bean id="tradeSqlItemReader"
class="org.springframework.batch.io.cursor.JdbcCursorItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.cursor.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="SELECT id, quantity, price, customer from TRADE" />
@@ -69,9 +64,7 @@
</bean>
<bean id="customerSqlItemReader"
class="org.springframework.batch.io.cursor.JdbcCursorItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.cursor.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="SELECT id, name, credit FROM customer " />

View File

@@ -1,84 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope"/>
<bean parent="jobConfigurationRegistryBeanPostProcessor"/>
<bean id="simpleSample" parent="simpleJob">
<property name="steps">
<list>
<bean id="step1" parent="simpleStep">
<property name="itemReader" ref="fileItemReader" />
<property name="itemReader" ref="fileItemReader" />
<property name="itemWriter">
<bean
class="org.springframework.batch.sample.tasklet.SimpleTradeWriter">
<property name="tradeDao" ref="tradeDao" />
</bean>
</property>
<property name="commitInterval" value="2" />
</bean>
</list>
</property>
</bean>
<bean id="tradeDao"
class="org.springframework.batch.sample.dao.JdbcTradeDao">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="incrementer">
<bean parent="incrementerParent">
<property name="incrementerName" value="TRADE_SEQ" />
</bean>
</property>
</bean>
<!-- This input source is injected into the test case to verify the output - not used by the job at all -->
<bean id="testInputTemplate" class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource" ref="fileLocator" />
<property name="lineTokenizer" ref="tradeTokenizer" />
<property name="fieldSetMapper" ref="tradeMapper" />
</bean>
<bean id="fileItemReader" parent="testInputTemplate"
autowire-candidate="false" scope="step">
<aop:scoped-proxy />
</bean>
<bean id="tradeMapper"
class="org.springframework.batch.sample.mapping.TradeFieldSetMapper" />
<bean id="fileLocator"
class="org.springframework.core.io.ClassPathResource">
<constructor-arg type="java.lang.String"
value="data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt" />
</bean>
<bean id="tradeTokenizer"
class="org.springframework.batch.io.file.transform.FixedLengthTokenizer">
<property name="names" value="ISIN, Quantity, Price, Customer" />
<property name="columns" value="1-12, 13-15, 16-20, 21-29" />
</bean>
<bean id="tradeLogAdvice"
class="org.springframework.batch.sample.advice.TradeWriterLogAdvice" />
<aop:config>
<aop:aspect id="tradeWriterLogging" ref="tradeLogAdvice">
<aop:after
pointcut="execution( * org.springframework.batch.sample.dao.TradeDao+.writeTrade(org.springframework.batch.sample.domain.Trade)) and args(trade)"
method="doBasicLogging" />
</aop:aspect>
</aop:config>
<bean parent="customEditorConfigurer" />
</beans>
<bean
class="org.springframework.batch.sample.tasklet.SimpleTradeWriter">
<property name="tradeDao" ref="tradeDao" />
</bean>
</property>
<property name="commitInterval" value="2" />
</bean>
</list>
</property>
</bean>
<bean id="tradeDao"
class="org.springframework.batch.sample.dao.JdbcTradeDao">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="incrementer">
<bean parent="incrementerParent">
<property name="incrementerName" value="TRADE_SEQ" />
</bean>
</property>
</bean>
<!-- This input source is injected into the test case to verify the output - not used by the job at all -->
<bean id="testInputTemplate"
class="org.springframework.batch.io.file.FlatFileItemReader">
<property name="resource" ref="fileLocator" />
<property name="lineTokenizer" ref="tradeTokenizer" />
<property name="fieldSetMapper" ref="tradeMapper" />
</bean>
<bean id="fileItemReader" parent="testInputTemplate"
autowire-candidate="false" />
<bean id="tradeMapper"
class="org.springframework.batch.sample.mapping.TradeFieldSetMapper" />
<bean id="fileLocator"
class="org.springframework.core.io.ClassPathResource">
<constructor-arg type="java.lang.String"
value="data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt" />
</bean>
<bean id="tradeTokenizer"
class="org.springframework.batch.io.file.transform.FixedLengthTokenizer">
<property name="names" value="ISIN, Quantity, Price, Customer" />
<property name="columns" value="1-12, 13-15, 16-20, 21-29" />
</bean>
<bean id="tradeLogAdvice"
class="org.springframework.batch.sample.advice.TradeWriterLogAdvice" />
<aop:config>
<aop:aspect id="tradeWriterLogging" ref="tradeLogAdvice">
<aop:after
pointcut="execution( * org.springframework.batch.sample.dao.TradeDao+.writeTrade(org.springframework.batch.sample.domain.Trade)) and args(trade)"
method="doBasicLogging" />
</aop:aspect>
</aop:config>
</beans>

View File

@@ -12,9 +12,6 @@
<import resource="tradeJobIo.xml" />
<bean parent="stepScope"/>
<bean parent="jobConfigurationRegistryBeanPostProcessor"/>
<bean id="tradeJob" parent="simpleJob">
<property name="steps">
<list>
@@ -55,9 +52,7 @@
</bean>
<bean id="tradeSqlItemReader"
class="org.springframework.batch.io.cursor.JdbcCursorItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.cursor.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="SELECT id, quantity, price, customer from TRADE" />
@@ -67,10 +62,7 @@
</property>
</bean>
<bean id="customerSqlItemReader" class="org.springframework.batch.io.cursor.JdbcCursorItemReader"
scope="step">
<aop:scoped-proxy />
<bean id="customerSqlItemReader" class="org.springframework.batch.io.cursor.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="SELECT id, name, credit FROM customer " />

View File

@@ -24,8 +24,7 @@
<bean
class="org.springframework.batch.sample.dao.FlatFileCustomerCreditWriter"
id="customerReportOutputSource" scope="step">
<aop:scoped-proxy />
id="customerReportOutputSource">
<property name="outputSource">
<bean
class="org.springframework.batch.io.file.FlatFileItemWriter"
@@ -40,8 +39,7 @@
</bean>
<bean class="org.springframework.batch.io.file.FlatFileItemReader"
id="fileInputTemplate" scope="step">
<aop:scoped-proxy />
id="fileInputTemplate">
<property name="resource" ref="fileLocator" />
<property name="lineTokenizer" ref="tradeFileDescriptor" />
<property name="fieldSetMapper">

View File

@@ -13,17 +13,12 @@
<import resource="../simple-container-definition.xml" />
<bean parent="stepScope" />
<bean parent="jobConfigurationRegistryBeanPostProcessor" />
<bean id="xmlStaxJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
<property name="itemReader">
<bean
class="org.springframework.batch.io.xml.StaxEventItemReader"
scope="step">
<aop:scoped-proxy />
class="org.springframework.batch.io.xml.StaxEventItemReader">
<property name="fragmentRootElementName"
value="trade" />
<property name="resource"
@@ -48,8 +43,7 @@
</bean>
<bean class="org.springframework.batch.io.xml.StaxEventItemWriter"
id="tradeStaxWriter" scope="step">
<aop:scoped-proxy />
id="tradeStaxWriter">
<property name="resource"
value="file:target/test-outputs/20070918.testStream.xmlFileStep.output.xml" />
<property name="serializer" ref="tradeMarshallingSerializer" />
@@ -77,7 +71,4 @@
<entry key="customer" value="java.lang.String" />
</util:map>
<!-- register the step scope with the application context -->
<bean class="org.springframework.batch.execution.scope.StepScope" />
</beans>

View File

@@ -11,10 +11,6 @@
<import resource="data-source-context.xml" />
<!-- register the step scope with the application context -->
<bean id="stepScope"
class="org.springframework.batch.execution.scope.StepScope" />
<bean id="jobConfigurationRegistryBeanPostProcessor" abstract="true"
class="org.springframework.batch.execution.configuration.JobRegistryBeanPostProcessor">
<property name="jobConfigurationRegistry"

View File

@@ -6,10 +6,6 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<import resource="classpath:data-source-context.xml" />
<!-- register the step scope with the application context -->
<bean id="stepScope"
class="org.springframework.batch.execution.scope.StepScope" />
<bean id="processor"
class="org.springframework.batch.sample.item.writer.StagingItemWriter">