Add MessageChannelPartitionHandler
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package org.springframework.batch.integration.partition;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.JobInterruptedException;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
|
||||
|
||||
public class BeanFactoryStepLocatorTests {
|
||||
|
||||
private BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator();
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
@Test
|
||||
public void testGetStep() throws Exception {
|
||||
beanFactory.registerSingleton("foo", new StubStep("foo"));
|
||||
stepLocator.setBeanFactory(beanFactory);
|
||||
assertNotNull(stepLocator.getStep("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStepNames() throws Exception {
|
||||
beanFactory.registerSingleton("foo", new StubStep("foo"));
|
||||
beanFactory.registerSingleton("bar", new StubStep("bar"));
|
||||
stepLocator.setBeanFactory(beanFactory);
|
||||
assertEquals(2, stepLocator.getStepNames().size());
|
||||
}
|
||||
|
||||
private static final class StubStep implements Step {
|
||||
|
||||
private String name;
|
||||
|
||||
public StubStep(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void execute(StepExecution stepExecution) throws JobInterruptedException {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getStartLimit() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isAllowStartIfComplete() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.springframework.batch.integration.partition;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.item.ItemStreamException;
|
||||
|
||||
/**
|
||||
* {@link ItemReader} with hard-coded input data.
|
||||
*/
|
||||
public class ExampleItemReader implements ItemReader<String>, ItemStream {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private String[] input = { "Hello", "world!", "Go", "on", "punk", "make", "my", "day!" };
|
||||
|
||||
private int index = 0;
|
||||
|
||||
public static volatile boolean fail = false;
|
||||
|
||||
/**
|
||||
* Reads next record from input
|
||||
*/
|
||||
public String read() throws Exception {
|
||||
if (index >= input.length) {
|
||||
return null;
|
||||
}
|
||||
logger.info(String.format("Processing input index=%s, item=%s, in (%s)", index, input[index], this));
|
||||
if (fail && index == 4) {
|
||||
synchronized (ExampleItemReader.class) {
|
||||
if (fail) {
|
||||
// Only fail once per flag setting...
|
||||
fail = false;
|
||||
logger.info(String.format("Throwing exception index=%s, item=%s, in (%s)", index, input[index],
|
||||
this));
|
||||
index++;
|
||||
throw new RuntimeException("Planned failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
return input[index++];
|
||||
}
|
||||
|
||||
public void close() throws ItemStreamException {
|
||||
}
|
||||
|
||||
public void open(ExecutionContext executionContext) throws ItemStreamException {
|
||||
index = (int) executionContext.getLong("POSITION", 0);
|
||||
}
|
||||
|
||||
public void update(ExecutionContext executionContext) throws ItemStreamException {
|
||||
executionContext.putLong("POSITION", index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.springframework.batch.integration.partition;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
public class ExampleItemReaderTests {
|
||||
|
||||
private ExampleItemReader reader = new ExampleItemReader();
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void ensureFailFlagUnset() {
|
||||
ExampleItemReader.fail = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
int count = 0;
|
||||
while (reader.read()!=null) {
|
||||
count++;
|
||||
}
|
||||
assertEquals(8, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpen() throws Exception {
|
||||
ExecutionContext context = new ExecutionContext();
|
||||
for (int i=0; i<4; i++) {
|
||||
reader.read();
|
||||
}
|
||||
reader.update(context);
|
||||
reader.open(context);
|
||||
int count = 0;
|
||||
while (reader.read()!=null) {
|
||||
count++;
|
||||
}
|
||||
assertEquals(4, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailAndRestart() throws Exception {
|
||||
ExecutionContext context = new ExecutionContext();
|
||||
ExampleItemReader.fail = true;
|
||||
for (int i=0; i<4; i++) {
|
||||
reader.read();
|
||||
reader.update(context);
|
||||
}
|
||||
try {
|
||||
reader.read();
|
||||
reader.update(context);
|
||||
fail("Expected Exception");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// expected
|
||||
assertEquals("Planned failure", e.getMessage());
|
||||
}
|
||||
assertFalse(ExampleItemReader.fail);
|
||||
reader.open(context);
|
||||
int count = 0;
|
||||
while (reader.read()!=null) {
|
||||
count++;
|
||||
}
|
||||
assertEquals(4, count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.springframework.batch.integration.partition;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
/**
|
||||
* Dummy {@link ItemWriter} which only logs data it receives.
|
||||
*/
|
||||
public class ExampleItemWriter implements ItemWriter<Object> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ExampleItemWriter.class);
|
||||
|
||||
/**
|
||||
* @see ItemWriter#write(List)
|
||||
*/
|
||||
public void write(List<? extends Object> data) throws Exception {
|
||||
log.info(data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.integration.partition;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.explore.JobExplorer;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class VanillaIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher;
|
||||
|
||||
@Autowired
|
||||
private Job job;
|
||||
|
||||
@Autowired
|
||||
private JobExplorer jobExplorer;
|
||||
|
||||
@Test
|
||||
public void testSimpleProperties() throws Exception {
|
||||
assertNotNull(jobLauncher);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchJob() throws Exception {
|
||||
int before = jobExplorer.getJobInstances(job.getName(), 0, 100).size();
|
||||
assertNotNull(jobLauncher.run(job, new JobParameters()));
|
||||
List<JobInstance> jobInstances = jobExplorer.getJobInstances(job.getName(), 0, 100);
|
||||
int after = jobInstances.size();
|
||||
assertEquals(1, after-before);
|
||||
JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size()-1)).get(0);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
assertEquals(3, jobExecution.getStepExecutions().size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,6 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %5p %t [%c] - <%m>%n
|
||||
|
||||
log4j.logger.org.springframework.batch=DEBUG
|
||||
log4j.logger.org.springframework.batch.core=DEBUG
|
||||
log4j.category.org.springframework.integration=DEBUG
|
||||
log4j.category.org.springframework.transaction=DEBUG
|
||||
@@ -10,10 +10,11 @@
|
||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
|
||||
<annotation-config/>
|
||||
<channel id="smokein"/>
|
||||
<channel id="smokeout">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
|
||||
|
||||
<import resource="classpath:/simple-job-launcher-context.xml" />
|
||||
|
||||
<integration:channel id="requests">
|
||||
<integration:queue />
|
||||
</integration:channel>
|
||||
<integration:channel id="staging">
|
||||
<integration:queue />
|
||||
</integration:channel>
|
||||
<integration:channel id="replies">
|
||||
<integration:queue />
|
||||
</integration:channel>
|
||||
|
||||
<integration:service-activator ref="stepExecutionRequestHandler"
|
||||
input-channel="requests" output-channel="staging">
|
||||
<integration:poller>
|
||||
<integration:interval-trigger interval="10"/>
|
||||
</integration:poller>
|
||||
</integration:service-activator>
|
||||
<integration:aggregator ref="partitionHandler"
|
||||
timeout="10000" input-channel="staging" output-channel="replies">
|
||||
<integration:poller>
|
||||
<integration:interval-trigger interval="10"/>
|
||||
</integration:poller>
|
||||
</integration:aggregator>
|
||||
|
||||
<!-- This is the "remote" worker (which in this case is local) -->
|
||||
<bean id="stepExecutionRequestHandler"
|
||||
class="org.springframework.batch.integration.partition.StepExecutionRequestHandler"
|
||||
p:jobExplorer-ref="jobExplorer" p:stepLocator-ref="stepLocator" />
|
||||
|
||||
<bean id="stepLocator"
|
||||
class="org.springframework.batch.integration.partition.BeanFactoryStepLocator" />
|
||||
|
||||
<bean id="jobExplorer"
|
||||
class="org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean" />
|
||||
|
||||
<bean id="partitionHandler"
|
||||
class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler">
|
||||
<property name="messagingGateway">
|
||||
<bean
|
||||
class="org.springframework.integration.gateway.SimpleMessagingGateway">
|
||||
<property name="requestChannel" ref="requests" />
|
||||
<property name="replyChannel" ref="replies" />
|
||||
<property name="replyTimeout" value="10000" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="stepName" value="step1" />
|
||||
<property name="gridSize" value="2" />
|
||||
</bean>
|
||||
|
||||
<bean id="job1" parent="simpleJob">
|
||||
<property name="steps">
|
||||
<bean name="step1:master"
|
||||
class="org.springframework.batch.core.partition.support.PartitionStep">
|
||||
<property name="partitionHandler" ref="partitionHandler" />
|
||||
<property name="stepExecutionSplitter">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<constructor-arg ref="jobRepository" />
|
||||
<constructor-arg ref="step1" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="step1" parent="simpleStep">
|
||||
<property name="itemReader">
|
||||
<bean
|
||||
class="org.springframework.batch.integration.partition.ExampleItemReader"
|
||||
scope="step">
|
||||
<!--
|
||||
<property name="resource"
|
||||
value="#{stepAttributes[jobParameters['resource']]}"/>
|
||||
-->
|
||||
</bean>
|
||||
</property>
|
||||
<property name="itemWriter">
|
||||
<bean
|
||||
class="org.springframework.batch.integration.partition.ExampleItemWriter" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user