Merge pull request #175 from gregturn/BATCH-2035

- Added a new archetype for javaconfig based projects
- Updated the CommandLineJobRunner to also accept class names for context initialization
This commit is contained in:
Greg Turnquist
2013-05-26 15:57:01 -04:00
committed by Michael Minella
parent 42dccf6efb
commit bb1ec38a18
19 changed files with 820 additions and 7 deletions

2
.gitignore vendored
View File

@@ -19,4 +19,4 @@ s3.properties
*.iws
.*.swp
.DS_Store
.springBeans

View File

@@ -14,6 +14,7 @@
</parent>
<modules>
<module>simple-cli</module>
<module>simple-cli-javaconfig</module>
</modules>
<build>
<pluginManagement>

View File

@@ -0,0 +1,286 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-simple-cli-javaconfig</artifactId>
<version>3.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Commandline</name>
<url>http://www.springframework.org/spring-batch/archetypes/simple-cli-archetype</url>
<description>This project is a command line batch sample from Spring Batch demonstrating a typical batch job.
The job can be invoked via "mvn exec:java" to see the job run from the command line.
During an "mvn package", a distribution archive in the format defined in src/main/assembly/descriptor.xml will
be created in the target directory which can be deployed and extracted to your target location of choice.
The ./bin/runJob.(sh|bat) script from the extracted deployment archive can be invoked to run the job.
</description>
<properties>
<spring.framework.version>3.2.0.RELEASE</spring.framework.version>
<spring.batch.version>3.0.0.BUILD-SNAPSHOT</spring.batch.version>
<dependency.locations.enabled>false</dependency.locations.enabled>
<junit.version>4.10</junit.version>
<compiler.target.version>1.6</compiler.target.version>
<compiler.source.version>1.6</compiler.source.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<profiles>
<profile>
<id>staging</id>
<distributionManagement>
<repository>
<id>staging</id>
<url>file:///${user.dir}/target/staging</url>
</repository>
<snapshotRepository>
<id>staging</id>
<url>file:///${user.dir}/target/staging</url>
</snapshotRepository>
</distributionManagement>
</profile>
<profile>
<id>bootstrap</id>
<pluginRepositories>
<pluginRepository>
<id>Codehaus</id>
<url>http://repository.codehaus.org/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>com.springsource.repository.bundles.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring.batch.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.0.0.RELEASE</version>
</extension>
</extensions>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<inherited>false</inherited>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[1.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${compiler.source.version}</source>
<target>${compiler.target.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<mainClass>org.springframework.batch.core.launch.support.CommandLineJobRunner</mainClass>
<arguments>
<argument>classpath:/launch-context.xml</argument>
<argument>personJob</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-distribution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<index>false</index>
<manifest>
<mainClass>org.springframework.batch.core.launch.support.CommandLineJobRunner</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<downloadUrl>http://www.springframework.org/download</downloadUrl>
<site>
<id>staging</id>
<url>file:///${user.dir}/target/staging/org.springframework.batch.archetype/${project.artifactId}</url>
</site>
<repository>
<id>spring-release</id>
<name>Spring Release Repository</name>
<url>file:///${user.dir}/target/staging/release</url>
</repository>
<snapshotRepository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>file:///${user.dir}/target/staging/snapshot</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@@ -0,0 +1,25 @@
<assembly>
<id>distribution</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/scripts</directory>
<outputDirectory>bin</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>resources</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<filtered>true</filtered>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View File

@@ -0,0 +1,94 @@
package example;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
@Configuration
@PropertySource("classpath:batch.properties")
@EnableBatchProcessing
@Import(ModuleContext.class)
public class LaunchContext {
@Autowired
Environment env;
@Bean
static PropertyPlaceholderConfigurer configurer() {
return new PropertyPlaceholderConfigurer();
}
@Bean
ItemReader<Person> itemReader() {
FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
reader.setResource(new ClassPathResource("support/sample-data.csv"));
reader.setLineMapper(new DefaultLineMapper<Person>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames(new String[] { "firstName", "lastName" });
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}});
}});
return reader;
}
@Bean
PersonItemProcessor itemProcess() {
return new PersonItemProcessor();
}
@Bean
ItemWriter<Person> itemWriter(DataSource dataSource) {
JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
writer.setSql(env.getProperty("person.insert.sql"));
writer.setDataSource(dataSource);
return writer;
}
@Bean
BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("batch.jdbc.driver"));
dataSource.setUrl(env.getProperty("batch.jdbc.url"));
dataSource.setUsername(env.getProperty("batch.jdbc.user"));
dataSource.setPassword(env.getProperty("batch.jdbc.password"));
return dataSource;
}
@Autowired
private ResourceLoader resourceLoader;
@PostConstruct
protected void initialize() throws Exception {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(this.resourceLoader.getResource(env.getProperty("batch.drop.script")));
populator.addScript(this.resourceLoader.getResource(env.getProperty("person.sql.location")));
populator.addScript(this.resourceLoader.getResource(env.getProperty("batch.schema.script")));
populator.setContinueOnError(true);
DatabasePopulatorUtils.execute(populator, dataSource());
}
}

View File

@@ -0,0 +1,37 @@
package example;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ModuleContext {
@Bean
public Job personJob(JobBuilderFactory jobs, Step s1) {
return jobs.get("personJob")
.incrementer(new RunIdIncrementer())
.flow(s1)
.end()
.build();
}
@Bean
public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader<Person> reader,
ItemWriter<Person> writer, ItemProcessor<Person, Person> processor) {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 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 example;
/**
* <p>
* Domain object representing information about a person.
* </p>
*/
public class Person {
private String lastName;
private String firstName;
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
@Override
public String toString() {
return "firstName: " + firstName + ", lastName: " + lastName;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 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 example;
import org.springframework.batch.item.ItemProcessor;
/**
* <p>
* An example {@link org.springframework.batch.item.ItemProcessor} implementation that upper cases attributes on the
* provided {@link Person} object.
* </p>
*/
public class PersonItemProcessor implements ItemProcessor<Person, Person> {
@Override
public Person process(final Person person) throws Exception {
final String firstName = person.getFirstName().toUpperCase();
final String lastName = person.getLastName().toUpperCase();
final Person transformedPerson = new Person();
transformedPerson.setFirstName(firstName);
transformedPerson.setLastName(lastName);
return transformedPerson;
}
}

View File

@@ -0,0 +1,15 @@
# Placeholders batch.*
# for HSQLDB:
batch.jdbc.driver=org.hsqldb.jdbcDriver
batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true
# use this one for a separate server process so you can inspect the results
# (or add it to system properties with -D to override at run time).
# batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples
batch.jdbc.user=sa
batch.jdbc.password=
batch.schema.script=classpath:org/springframework/batch/core/schema-hsqldb.sql
batch.drop.script=classpath:org/springframework/batch/core/schema-drop-hsqldb.sql
person.sql.location=classpath:support/person.sql
person.test.data.location=classpath:support/sample-data.csv
person.insert.sql=INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)
step1.commit.interval=5

View File

@@ -0,0 +1,8 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
log4j.category.org.springframework.batch=DEBUG
log4j.category.org.springframework.transaction=INFO

View File

@@ -0,0 +1,7 @@
DROP TABLE people IF EXISTS;
CREATE TABLE people (
person_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
first_name VARCHAR(20),
last_name VARCHAR(20)
);

View File

@@ -0,0 +1,5 @@
Jill,Doe
Joe,Doe
Justin,Doe
Jane,Doe
John,Doe
1 Jill Doe
2 Joe Doe
3 Justin Doe
4 Jane Doe
5 John Doe

View File

@@ -0,0 +1,8 @@
@echo off
IF NOT DEFINED JAVA_HOME (
echo Error: JAVA_HOME environment variable is not set.
EXIT /B
)
%JAVA_HOME%\bin\java -cp resources\;lib\* org.springframework.batch.core.launch.support.CommandLineJobRunner classpath:/launch-context.xml personJob

View File

@@ -0,0 +1,8 @@
#!/bin/bash
if [ "$JAVA_HOME" = "" ]; then
echo "Error: JAVA_HOME environment variable is not set."
exit 1
fi
$JAVA_HOME/bin/java -cp resources/:lib/* org.springframework.batch.core.launch.support.CommandLineJobRunner classpath:/launch-context.xml personJob

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Spring Batch: ${project.name}">
<bannerLeft>
<name>Spring Batch: ${project.name}</name>
<href>index.html</href>
</bannerLeft>
<skin>
<groupId>org.springframework.maven.skins</groupId>
<artifactId>maven-spring-skin</artifactId>
<version>1.0.5</version>
</skin>
<body>
<links>
<item name="${project.name}" href="index.html"/>
</links>
<menu ref="reports"/>
</body>
</project>

View File

@@ -0,0 +1,38 @@
/*
* Copyright 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 example;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* <p>
* Example test case processing a {@link Person} using the {@link PersonItemProcessor}.
* </p>
*/
public class PersonItemProcessorTest {
@Test
public void testProcessedPersonRecord() throws Exception {
final Person person = new Person();
person.setFirstName("Jane");
person.setLastName("Doe");
final Person processedPerson = new PersonItemProcessor().process(person);
assertEquals("First name does not match expected value.", "JANE", processedPerson.getFirstName());
assertEquals("Last name does not match expected value.", "DOE", processedPerson.getLastName());
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.
* 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 example;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
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.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* <p>
* Test cases asserting on the example job's configuration.
* </p>
*/
@ContextConfiguration(classes=TestContext.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class PersonJobConfigurationTest {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Autowired
private JobOperator jobOperator;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
/**
* <p>
* Creates a new {@link JobExecution} using a {@link JobLauncher}.
* </p>
*
* @throws Exception if any {@link Exception}'s occur
*/
@Test
public void testLaunchJobWithJobLauncher() throws Exception {
final JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
assertEquals("Batch status not COMPLETED", BatchStatus.COMPLETED, jobExecution.getStatus());
}
/**
* <p>
* Create a unique job instance and check it's execution completes successfully.
* Uses the convenience methods provided by the testing superclass.
* </p>
*
* @throws Exception if any {@link Exception}'s occur
*/
@Test
public void testLaunchJob() throws Exception {
final JobExecution jobExecution = jobLauncherTestUtils.launchJob(jobLauncherTestUtils.getUniqueJobParameters());
assertEquals("Batch status not COMPLETED", BatchStatus.COMPLETED, jobExecution.getStatus());
}
/**
* <p>
* Execute a fresh {@link JobInstance} using {@link JobOperator} which is closer to
* a remote invocation scenario.
* </p>
*
* @throws Exception if any {@link Exception}'s occur
*/
@Test
public void testLaunchByJobOperator() throws Exception {
final long jobExecutionId = jobOperator.startNextInstance(jobLauncherTestUtils.getJob().getName());
final String result = jobOperator.getSummary(jobExecutionId);
assertTrue("Result does not contain status=COMPLETED", result.contains("status=" + BatchStatus.COMPLETED));
}
}

View File

@@ -0,0 +1,59 @@
package example;
import javax.sql.DataSource;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.configuration.support.MapJobRegistry;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.launch.support.SimpleJobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@EnableBatchProcessing
@Import(LaunchContext.class)
public class TestContext {
@Bean
JobLauncherTestUtils jobLauncherTestUtils() {
return new JobLauncherTestUtils();
}
@Bean
JobOperator jobOperator(final JobLauncher jobLauncher, final JobExplorer jobExplorer,
final JobRepository jobRepository, final JobRegistry jobRegistry) {
return new SimpleJobOperator() {{
setJobLauncher(jobLauncher);
setJobExplorer(jobExplorer);
setJobRepository(jobRepository);
setJobRegistry(jobRegistry);
}};
}
@Bean
JobExplorerFactoryBean jobExplorer(final DataSource dataSource) {
return new JobExplorerFactoryBean() {{
setDataSource(dataSource);
}};
}
@Bean
MapJobRegistry jobRegister() {
return new MapJobRegistry();
}
@Bean
JobRegistryBeanPostProcessor jobRegisterBeanPostProcess(final JobRegistry jobRegistry) {
return new JobRegistryBeanPostProcessor() {{
setJobRegistry(jobRegistry);
}};
}
}

View File

@@ -47,10 +47,13 @@ import org.springframework.batch.core.launch.JobExecutionNotRunningException;
import org.springframework.batch.core.launch.JobExecutionNotStoppedException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobParametersNotFoundException;
import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -281,7 +284,12 @@ public class CommandLineJobRunner {
ConfigurableApplicationContext context = null;
try {
context = new ClassPathXmlApplicationContext(jobPath);
try {
context = new ClassPathXmlApplicationContext(jobPath);
} catch (BeansException e) {
logger.info("No XML-based context named " + jobPath + ". Trying class-based configuration.");
context = new AnnotationConfigApplicationContext(Class.forName(jobPath));
}
context.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
@@ -292,7 +300,7 @@ public class CommandLineJobRunner {
}
String jobName = jobIdentifier;
JobParameters jobParameters = jobParametersConverter.getJobParameters(StringUtils
.splitArrayElementsIntoProperties(parameters, "="));
Assert.isTrue(parameters == null || parameters.length == 0 || !jobParameters.isEmpty(),
@@ -333,11 +341,14 @@ public class CommandLineJobRunner {
jobName = jobExecution.getJobInstance().getJobName();
}
Job job;
Job job = null;
if (jobLocator != null) {
job = jobLocator.getJob(jobName);
try {
job = jobLocator.getJob(jobName);
} catch (NoSuchJobException e) {
}
}
else {
if (job == null) {
job = (Job) context.getBean(jobName);
}
@@ -566,7 +577,7 @@ public class CommandLineJobRunner {
}
if (jobPath == null || jobIdentifier == null) {
String message = "At least 2 arguments are required: JobPath and jobIdentifier.";
String message = "At least 2 arguments are required: JobPath/JobClass and jobIdentifier.";
logger.error(message);
CommandLineJobRunner.message = message;
command.exit(1);