BATCHADM-161 - Add Job Launching Gateway

For reference see: https://jira.springsource.org/browse/BATCHADM-161

* Add XML Schema
* Add Namespace Handler
* Add Parser and Gateway classes
* Add tests
This commit is contained in:
Gunnar Hillert
2013-05-01 12:47:45 -04:00
committed by Michael Minella
parent f23dd64740
commit 3909b75151
20 changed files with 904 additions and 4 deletions

View File

@@ -108,6 +108,18 @@
<artifactId>spring-integration-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>${spring.integration.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>junit-dep</artifactId>
<groupId>junit</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2013 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.config.xml;
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
/**
* The namespace handler for the Spring Batch Integration namespace.
*
* @author Gunnar Hillert
* @since 1.3
*
*/
public class BatchIntegrationNamespaceHandler extends AbstractIntegrationNamespaceHandler {
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init() {
this.registerBeanDefinitionParser("job-launching-gateway", new JobLaunchingGatewayParser());
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2002-2013 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.config.xml;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.integration.launch.JobLaunchingGateway;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* The parser for the Job-Launching Gateway, which will instantiate a
* {@link JobLaunchingGatewayParser}. If no {@link JobLauncher} reference has
* been provided, this parse will use the use the globally registered bean
* 'jobLauncher'.
*
* @author Gunnar Hillert
* @since 1.3
*
*/
public class JobLaunchingGatewayParser extends AbstractConsumerEndpointParser {
private static final Log logger = LogFactory.getLog(JobLaunchingGatewayParser.class);
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
}
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
final BeanDefinitionBuilder jobLaunchingGatewayBuilder =
BeanDefinitionBuilder.genericBeanDefinition(JobLaunchingGateway.class);
final String jobLauncher = element.getAttribute("job-launcher");
if (StringUtils.hasText(jobLauncher)) {
jobLaunchingGatewayBuilder.addConstructorArgReference(jobLauncher);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No jobLauncher specified, using default 'jobLauncher' reference instead.");
}
jobLaunchingGatewayBuilder.addConstructorArgReference("jobLauncher");
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(jobLaunchingGatewayBuilder, element, "reply-timeout", "sendTimeout");
final String replyChannel = element.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
jobLaunchingGatewayBuilder.addPropertyReference("outputChannel", replyChannel);
}
return jobLaunchingGatewayBuilder;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2002-2013 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.launch;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.util.Assert;
/**
* The {@link JobLaunchingGateway} is used to launch Batch Jobs. Internally it
* delegates to a {@link JobLaunchingMessageHandler}.
*
* @author Gunnar Hillert
*
* @since 1.3
*/
public class JobLaunchingGateway extends AbstractReplyProducingMessageHandler {
private final JobLaunchingMessageHandler jobLaunchingMessageHandler;
/**
* Constructor taking a {@link JobLauncher} as parameter.
*
* @param storedProcExecutor Must not be null.
*
*/
public JobLaunchingGateway(JobLauncher jobLauncher) {
Assert.notNull(jobLauncher, "jobLauncher must not be null.");
this.jobLaunchingMessageHandler = new JobLaunchingMessageHandler(jobLauncher);
}
/**
* Launches a Batch Job using the provided request {@link Message}. The payload
* of the {@link Message} <em>must</em> be an instance of {@link JobLaunchRequest}.
*
* @param The provided requestMessage must not be null.
* @return Generally a {@link JobExecution} will always be returned. An
* exception ({@link MessageHandlingException}) will only be thrown if there
* is a failure to start the job. The cause of the exception will be a
* {@link JobExecutionException}.
*
* @throws MessageHandlingException
*/
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Assert.notNull(requestMessage, "The provided requestMessage must not be null.");
final Object payload = requestMessage.getPayload();
Assert.isInstanceOf(JobLaunchRequest.class, payload, "The payload must be of type JobLaunchRequest.");
final JobLaunchRequest jobLaunchRequest = (JobLaunchRequest) payload;
final JobExecution jobExecution;
try {
jobExecution = this.jobLaunchingMessageHandler.launch(jobLaunchRequest);
} catch (JobExecutionException e) {
throw new MessageHandlingException(requestMessage, e);
}
return jobExecution;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2007 the original author or authors.
* Copyright 2006-2013 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.
@@ -27,7 +27,8 @@ import org.springframework.integration.annotation.ServiceActivator;
* Message handler which uses strategies to convert a Message into a job and a set of job parameters
* @author Jonas Partner
* @author Dave Syer
*
* @author Gunnar Hillert
*
*/
public class JobLaunchingMessageHandler implements JobLaunchRequestHandler {
@@ -46,8 +47,7 @@ public class JobLaunchingMessageHandler implements JobLaunchRequestHandler {
Job job = request.getJob();
JobParameters jobParameters = request.getJobParameters();
JobExecution execution = jobLauncher.run(job, jobParameters);
return execution;
return jobLauncher.run(job, jobParameters);
}
}

View File

@@ -0,0 +1 @@
http\://www.springframework.org/schema/batch-integration=org.springframework.batch.integration.config.xml.BatchIntegrationNamespaceHandler

View File

@@ -0,0 +1,2 @@
http\://www.springframework.org/schema/batch-integration/spring-batch-integration-1.3.xsd=org/springframework/batch/integration/config/xml/spring-batch-integration-1.3.xsd
http\://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd=org/springframework/batch/integration/config/xml/spring-batch-integration-1.3.xsd

View File

@@ -0,0 +1,4 @@
# Tooling related information for the Spring Batch Integration namespace
http\://www.springframework.org/schema/integration/spring-batch-integration@name=Spring Batch Integration Namespace
http\://www.springframework.org/schema/integration/spring-batch-integration@prefix=batch-int
http\://www.springframework.org/schema/integration/spring-batch-integration@icon=org/springframework/batch/integration/config/xml/spring-batch-integration.gif

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/batch-integration"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/batch-integration"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration.xsd" />
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for the Spring Batch Integration
Support.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="job-launching-gateway">
<xsd:annotation>
<xsd:documentation><![CDATA[
This Outbound Gateway is used to launch Batch Jobs. The
payload of Messages to be processed MUST be an instance
of JobLaunchRequest.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attributeGroup ref="corespringBatchIntegrationComponentAttributes"/>
<xsd:attribute name="request-channel" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The input Message Channel of this endpoint.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Message Channel to which the resulting JobExecution
payload will be sent.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Allows you to specify how long this gateway will wait for
the reply message to be sent successfully to the reply channel
before throwing an exception. This attribute only applies when the
channel might block, for example when using a bounded queue channel that
is currently full.
Also, keep in mind that when sending to a DirectChannel, the
invocation will occur in the sender's thread. Therefore,
the failing of the send operation may be caused by other
components further downstream.
The "reply-timeout" attribute maps to the "sendTimeout" property of the
underlying 'MessagingTemplate' instance (org.springframework.integration.core.MessagingTemplate).
The attribute will default, if not specified, to '-1', meaning that
by default, the Gateway will wait indefinitely. The value is
specified in milliseconds.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="job-launcher" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation><![CDATA[
Pass in a custom JobLauncher bean reference.
This attribute is optional. If not specified the
adapter will re-use the default instance (under
the id 'jobLauncher', e.g. when using the
@EnableBatchProcessing annotation via JavaConfig).
If no default instance exists an exception is
thrown.
]]></xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.batch.core.launch.JobLauncher" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the order for invocation when this endpoint
is connected as a subscriber to a SubscribableChannel.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="corespringBatchIntegrationComponentAttributes">
<xsd:attribute name="id" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Identifies the underlying Spring bean definition, which is an
instance of either 'EventDrivenConsumer' or 'PollingConsumer',
depending on whether the component's input channel is a
'SubscribableChannel' or 'PollableChannel'.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="auto-startup" default="true" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Flag to indicate that the component should start automatically
on startup (default true).
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
</xsd:schema>

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2002-2013 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.config.xml;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.context.annotation.Configuration;
/**
*
* @author Gunnar Hillert
* @since 1.3
*
*/
@Configuration
@EnableBatchProcessing
public class JobLauncherParserTestsConfiguration {
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2002-2013 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.config.xml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.After;
import org.junit.Test;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.integration.launch.JobLaunchingMessageHandler;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.test.util.TestUtils;
/**
*
* @author Gunnar Hillert
* @since 1.3
*
*/
public class JobLaunchingGatewayParserTests {
private ConfigurableApplicationContext context;
private EventDrivenConsumer consumer;
@Test
public void testGatewayParser() throws Exception {
setUp("JobLaunchingGatewayParserTests-context.xml", getClass());
final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", AbstractMessageChannel.class);
assertEquals("requestChannel", inputChannel.getComponentName());
final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class);
assertNotNull(jobLaunchingMessageHandler);
final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, "handler.messagingTemplate", MessagingTemplate.class);
final Long sendTimeout = TestUtils.getPropertyValue(messagingTemplate, "sendTimeout", Long.class);
assertEquals("Wrong sendTimeout", Long.valueOf(123L), sendTimeout);
assertFalse(this.consumer.isRunning());
}
@Test
public void testJobLaunchingGatewayIsRunning() throws Exception {
setUp("JobLaunchingGatewayParserTestsRunning-context.xml", getClass());
assertTrue(this.consumer.isRunning());
final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, "handler.messagingTemplate", MessagingTemplate.class);
final Long sendTimeout = TestUtils.getPropertyValue(messagingTemplate, "sendTimeout", Long.class);
assertEquals("Wrong sendTimeout", Long.valueOf(-1L), sendTimeout);
}
@Test
public void testJobLaunchingGatewayNoJobLauncher() throws Exception {
try {
setUp("JobLaunchingGatewayParserTestsNoJobLauncher-context.xml", getClass());
}
catch(BeanCreationException e) {
assertEquals("No bean named 'jobLauncher' is defined", e.getCause().getMessage());
return;
}
fail("Expected a NoSuchBeanDefinitionException to be thrown.");
}
@Test
public void testJobLaunchingGatewayWithEnableBatchProcessing() throws Exception {
setUp("JobLaunchingGatewayParserTestsWithEnableBatchProcessing-context.xml", getClass());
final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class);
assertNotNull(jobLaunchingMessageHandler);
final JobLauncher jobLauncher = TestUtils.getPropertyValue(jobLaunchingMessageHandler, "jobLauncher", JobLauncher.class);
assertNotNull(jobLauncher);
}
@After
public void tearDown(){
if(context != null){
context.close();
}
}
public void setUp(String name, Class<?> cls){
context = new ClassPathXmlApplicationContext(name, cls);
consumer = this.context.getBean("batchjobExecutor", EventDrivenConsumer.class);
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2002-2013 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.launch;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.integration.JobSupport;
import org.springframework.batch.integration.step.TestTasklet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.MessageHeaders;
import org.springframework.integration.MessagingException;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
*
* @author Gunnar Hillert
* @since 1.3
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class JobLaunchingGatewayIntegrationTests {
@Autowired
@Qualifier("requests")
private MessageChannel requestChannel;
@Autowired
@Qualifier("response")
private PollableChannel responseChannel;
@Autowired
private TestTasklet tasklet;
@Autowired
private Job testJob;
private JobSupport job = new JobSupport("testJob");
@Before
public void setUp() {
Object message = "";
while (message!=null) {
message = responseChannel.receive(10L);
}
}
@Test
@DirtiesContext
@SuppressWarnings("unchecked")
public void testNoReply() {
GenericMessage<JobLaunchRequest> trigger = new GenericMessage<JobLaunchRequest>(new JobLaunchRequest(job,
new JobParameters()));
try {
requestChannel.send(trigger);
}
catch (MessagingException e) {
String message = e.getMessage();
assertTrue("Wrong message: " + message, message.contains("replyChannel"));
}
Message<JobExecution> executionMessage = (Message<JobExecution>) responseChannel.receive(1000);
assertNull("JobExecution message received when no return address set", executionMessage);
}
@SuppressWarnings("unchecked")
@Test
@DirtiesContext
public void testReply() {
JobParametersBuilder builder = new JobParametersBuilder();
builder.addString("dontclash", "12");
Map<String, Object> map = new HashMap<String, Object>();
map.put(MessageHeaders.REPLY_CHANNEL, "response");
MessageHeaders headers = new MessageHeaders(map);
GenericMessage<JobLaunchRequest> trigger = new GenericMessage<JobLaunchRequest>(new JobLaunchRequest(job,
builder.toJobParameters()), headers);
requestChannel.send(trigger);
Message<JobExecution> executionMessage = (Message<JobExecution>) responseChannel.receive(1000);
assertNotNull("No response received", executionMessage);
JobExecution execution = executionMessage.getPayload();
assertNotNull("JobExecution not returned", execution);
}
@Test
@DirtiesContext
@SuppressWarnings("unchecked")
public void testWrongPayload() {
final Message<String> stringMessage = MessageBuilder.withPayload("just text").build();
try {
requestChannel.send(stringMessage);
}
catch (MessageHandlingException e) {
String message = e.getCause().getMessage();
assertTrue("Wrong message: " + message, message.contains("The payload must be of type JobLaunchRequest."));
}
Message<JobExecution> executionMessage = (Message<JobExecution>) responseChannel.receive(1000);
assertNull("JobExecution message received when no return address set", executionMessage);
}
@Test
@DirtiesContext
@SuppressWarnings("unchecked")
public void testExceptionRaised() throws InterruptedException {
this.tasklet.setFail(true);
JobParametersBuilder builder = new JobParametersBuilder();
builder.addString("dontclash", "12");
Map<String, Object> map = new HashMap<String, Object>();
map.put(MessageHeaders.REPLY_CHANNEL, "response");
MessageHeaders headers = new MessageHeaders(map);
GenericMessage<JobLaunchRequest> trigger = new GenericMessage<JobLaunchRequest>(new JobLaunchRequest(testJob,
builder.toJobParameters()), headers);
requestChannel.send(trigger);
Message<JobExecution> executionMessage = (Message<JobExecution>) responseChannel.receive(1000);
assertNotNull("No response received", executionMessage);
JobExecution execution = executionMessage.getPayload();
assertNotNull("JobExecution not returned", execution);
assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode());
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2013 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.launch;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.integration.JobSupport;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.support.MessageBuilder;
/**
*
* @author Gunnar Hillert
* @since 1.3
*
*/
public class JobLaunchingGatewayTests {
@Test
public void testExceptionRaised() throws Exception {
final Message<JobLaunchRequest> message = MessageBuilder.withPayload(new JobLaunchRequest(new JobSupport("testJob"),
new JobParameters())).build();
final JobLauncher jobLauncher = mock(JobLauncher.class);
when(jobLauncher.run(any(Job.class), any(JobParameters.class)))
.thenThrow(new JobParametersInvalidException("This is a JobExecutionException."));
JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(jobLauncher);
try {
jobLaunchingGateway.handleMessage(message);
}
catch (MessageHandlingException e) {
assertEquals("This is a JobExecutionException.", e.getCause().getMessage());
return;
}
fail("Expecting a MessageHandlingException to be thrown.");
}
}

View File

@@ -0,0 +1,31 @@
<?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:int="http://www.springframework.org/schema/integration"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
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.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<import resource="batch-setup-context.xml"/>
<int:channel id="requestChannel"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<batch-int:job-launching-gateway id="batchjobExecutor" reply-timeout="123"
auto-startup="false"
request-channel="requestChannel"
reply-channel="replyChannel"
job-launcher="jobLauncher"/>
</beans>

View File

@@ -0,0 +1,26 @@
<?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:int="http://www.springframework.org/schema/integration"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
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.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<import resource="batch-setup-context.xml"/>
<int:channel id="requestChannel"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
<batch-int:job-launching-gateway id="batchjobExecutor"
auto-startup="true"
request-channel="requestChannel"
reply-channel="replyChannel"/>
</beans>

View File

@@ -0,0 +1,31 @@
<?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:int="http://www.springframework.org/schema/integration"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
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.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<import resource="batch-setup-context.xml"/>
<int:channel id="requestChannel"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<batch-int:job-launching-gateway id="batchjobExecutor"
auto-startup="true"
request-channel="requestChannel"
reply-channel="replyChannel"
job-launcher="jobLauncher"/>
</beans>

View File

@@ -0,0 +1,30 @@
<?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:int="http://www.springframework.org/schema/integration"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<context:annotation-config />
<bean class="org.springframework.batch.integration.config.xml.JobLauncherParserTestsConfiguration"/>
<int:channel id="requestChannel"/>
<int:channel id="replyChannel">
<int:queue/>
</int:channel>
<batch-int:job-launching-gateway id="batchjobExecutor"
auto-startup="true"
request-channel="requestChannel"
reply-channel="replyChannel"/>
</beans>

View File

@@ -0,0 +1,28 @@
<?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:int="http://www.springframework.org/schema/integration"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:batch-int="http://www.springframework.org/schema/batch-integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
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.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<jdbc:embedded-database id="dataSource" type="HSQL"/>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:/org/springframework/batch/core/schema-drop-hsqldb.sql"/>
<jdbc:script location="classpath:/org/springframework/batch/core/schema-hsqldb.sql"/>
</jdbc:initialize-database>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<batch:job-repository data-source="dataSource" id="jobRepository"
transaction-manager="transactionManager" table-prefix="BATCH_"/>
</beans>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch-integration="http://www.springframework.org/schema/batch-integration"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/batch-integration http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<import resource="classpath:simple-job-launcher-context.xml" />
<integration:annotation-config/>
<integration:channel id="requests" />
<integration:channel id="response">
<integration:queue/>
</integration:channel>
<batch-integration:job-launching-gateway request-channel="requests" job-launcher="jobLauncher" />
<bean id="testJob" parent="simpleJob">
<property name="steps" ref="step" />
</bean>
<bean id="step" parent="taskletStep">
<property name="tasklet" ref="tasklet"/>
</bean>
<bean id="tasklet" class="org.springframework.batch.integration.step.TestTasklet" />
</beans>