diff --git a/.gitignore b/.gitignore
index fbc1fdffff..97b1d8a064 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,10 @@ s3.properties
*.iws
.*.swp
.DS_Store
+.springBeans
+build
+.gradle
+pom.xml
+out
+/.gradletasknamecache
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6bf47b00a8..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: java
-
-install: mvn -U install --quiet -DskipTests=true -P bootstrap
-script: mvn clean test -P bootstrap
diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc
new file mode 100644
index 0000000000..d5e7178131
--- /dev/null
+++ b/CODE_OF_CONDUCT.adoc
@@ -0,0 +1,44 @@
+= Contributor Code of Conduct
+
+As contributors and maintainers of this project, and in the interest of fostering an open
+and welcoming community, we pledge to respect all people who contribute through reporting
+issues, posting feature requests, updating documentation, submitting pull requests or
+patches, and other activities.
+
+We are committed to making participation in this project a harassment-free experience for
+everyone, regardless of level of experience, gender, gender identity and expression,
+sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
+religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information, such as physical or electronic addresses,
+ without explicit permission
+* Other unethical or unprofessional conduct
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments,
+commits, code, wiki edits, issues, and other contributions that are not aligned to this
+Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
+that they deem inappropriate, threatening, offensive, or harmful.
+
+By adopting this Code of Conduct, project maintainers commit themselves to fairly and
+consistently applying these principles to every aspect of managing this project. Project
+maintainers who do not follow or enforce the Code of Conduct may be permanently removed
+from the project team.
+
+This Code of Conduct applies both within project spaces and in public spaces when an
+individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
+contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
+be reviewed and investigated and will result in a response that is deemed necessary and
+appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
+with regard to the reporter of an incident.
+
+This Code of Conduct is adapted from the
+https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
+https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..0ab0cb732f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,193 @@
+Contributor Guidelines
+======================
+
+Have something you'd like to contribute to **Spring Batch**? We welcome pull requests, but ask that you carefully read this document first to understand how best to submit them; what kind of changes are likely to be accepted; and what to expect from the Spring team when evaluating your submission.
+
+Please refer back to this document as a checklist before issuing any pull request; this will save time for everyone!
+
+## Understand the basics
+
+Not sure what a *pull request* is, or how to submit one? Take a look at GitHub's excellent [help documentation][] first.
+
+## Search JIRA first; create an issue if necessary
+
+Is there already an issue that addresses your concern? Do a bit of searching in our [JIRA issue tracker][] to see if you can find something similar. If not, please create a new issue before submitting a pull request unless the change is truly trivial, e.g. typo fixes, removing compiler warnings, etc.
+
+## Sign the contributor license agreement
+
+If you have not previously done so, please fill out and
+submit the [Contributor License Agreement](https://cla.pivotal.io/sign/spring).
+
+## Fork the Repository
+
+1. Go to [https://github.com/spring-projects/spring-batch](https://github.com/spring-projects/spring-batch)
+2. Hit the "fork" button and choose your own github account as the target
+3. For more details see [https://help.github.com/fork-a-repo/](https://help.github.com/fork-a-repo/)
+
+## Setup your Local Development Environment
+
+1. `git clone git@github.com:/spring-batch.git`
+2. `cd spring-batch`
+3. `git remote show`
+_you should see only 'origin' - which is the fork you created for your own github account_
+4. `git remote add upstream git@github.com:spring-projects/spring-batch.git`
+5. `git remote show`
+_you should now see 'upstream' in addition to 'origin' where 'upstream' is the *spring-projects*repository from which releases are built_
+6. `git fetch --all`
+7. `git branch -a`
+_you should see branches on origin as well as upstream, including 'master'_
+
+## A Day in the Life of a Contributor
+
+* _Always_ work on topic branches (Typically use the Jira ticket ID as the branch name).
+ - For example, to create and switch to a new branch for issue BATCH-123: `git checkout -b BATCH-123`
+* You might be working on several different topic branches at any given time, but when at a stopping point for one of those branches, commit (a local operation).
+* Please follow the "Commit Guidelines" described in this chapter of Pro Git: [https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines)
+* Then to begin working on another issue (say BATCH-101): `git checkout BATCH-101`. The _-b_ flag is not needed if that branch already exists in your local repository.
+* When ready to resolve an issue or to collaborate with others, you can push your branch to origin (your fork), e.g.: `git push origin BATCH-123`
+* If you want to collaborate with another contributor, have them fork your repository (add it as a remote) and `git fetch ` to grab your branch. Alternatively, they can use `git fetch --all` to sync their local state with all of their remotes.
+* If you grant that collaborator push access to your repository, they can even apply their changes to your branch.
+* When ready for your contribution to be reviewed for potential inclusion in the master branch of the canonical *spring-batch* repository (what you know as 'upstream'), issue a pull request to the *spring-projects* repository (for more detail, see [https://help.github.com/send-pull-requests/](https://help.github.com/send-pull-requests/)).
+* The project lead may merge your changes into the upstream master branch as-is, he may keep the pull request open yet add a comment about something that should be modified, or he might reject the pull request by closing it.
+* A prerequisite for any pull request is that it will be cleanly merge-able with the upstream master's current state. **This is the responsibility of any contributor.** If your pull request cannot be applied cleanly, the project lead will most likely add a comment requesting that you make it merge-able. For a full explanation, see the Pro Git section on rebasing: [https://git-scm.com/book/en/v2/Git-Branching-Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing). As stated there: "> Often, you’ll do this to make sure your commits apply cleanly on a remote branch — perhaps in a project to which you’re trying to contribute but that you don’t maintain."
+
+## Keeping your Local Code in Sync
+* As mentioned above, you should always work on topic branches (since 'master' is a moving target). However, you do want to always keep your own 'origin' master branch in synch with the 'upstream' master.
+* Within your local working directory, you can sync up all remotes' branches with: `git fetch --all`
+* While on your own local master branch: `git pull upstream master` (which is the equivalent of fetching upstream/master and merging that into the branch you are in currently)
+* Now that you're in synch, switch to the topic branch where you plan to work, e.g.: `git checkout -b BATCH-123`
+* When you get to a stopping point: `git commit`
+* If changes have occurred on the upstream/master while you were working you can synch again:
+ - Switch back to master: `git checkout master`
+ - Then: `git pull upstream master`
+ - Switch back to the topic branch: `git checkout BATCH-123` (no -b needed since the branch already exists)
+ - Rebase the topic branch to minimize the distance between it and your recently synched master branch: `git rebase master`
+(Again, for more detail see the Pro Git section on rebasing: [https://git-scm.com/book/en/v2/Git-Branching-Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing))
+* **Note** You cannot rebase if you have already pushed your branch to your remote because you'd be rewriting history (see **'The Perils of Rebasing'** in the article). If you rebase by mistake, you can undo it as discussed [in this stackoverflow discussion](https://stackoverflow.com/questions/134882/undoing-a-git-rebase). Once you have published your branch, you need to merge in the master rather than rebasing.
+* Now, if you issue a pull request, it is much more likely to be merged without conflicts. Most likely, any pull request that would produce conflicts will be deferred until the issuer of that pull request makes these adjustments.
+* Assuming your pull request is merged into the 'upstream' master, you will actually end up pulling that change into your own master eventually, and at that time, you may decide to delete the topic branch from your local repository and your fork (origin) if you pushed it there.
+ - to delete the local branch: `git branch -d BATCH-123`
+ - to delete the branch from your origin: `git push origin :BATCH-123`
+
+## Maintain a linear commit history
+
+When issuing pull requests, please ensure that your commit history is linear. From the command line you can check this using:
+
+````
+log --graph --pretty=oneline
+````
+
+As this may cause lots of typing, we recommend creating a global alias, e.g. `git logg` for this:
+
+````
+git config --global alias.logg 'log --graph --pretty=oneline'
+````
+
+This command, will provide the following output, which in this case shows a nice linear history:
+
+````
+* e1f6de38e04a5227fea2d4df193a5b50beaf2d00 BATCH-2002: Initial support for complex conditional replacements
+* 65d2df652abaae2ca309d96e3026c2d67312655f Add ability to set a custom TaskExecutor impl, remove unused namespaces from JSR bootst
+* 85807568575c24d8878ad605a344f2bc35bb2b13 Update to allow restart parameters to override previous parameters in JsrJobOperator an
+* a21df75ce9dfc92e9768353b827da4248aefe425 BATCH-2049: Support multiple fragmentRootElementNames in StaxEventItemReader
+* 7f1130c9a265a3ce18a46cbbc122e6573167a036 Fix TCK test JobOperatorTests.testJobOperatorRestartJobAlreadyAbandoned
+* c4231c4cc861bbcc43437c80a03ddd9b7b2897a3 Fixed no executions returned check and added a unit test
+````
+If you see intersecting lines, that usually means that you forgot to rebase you branch. As mentioned earlier, **please rebase against master** before issuing a pull request.
+
+## Code style
+
+Please carefully follow the same [code style as Spring Framework](https://github.com/spring-projects/spring-framework/wiki/Code-Style).
+
+## Add Apache license header to all new classes
+
+```java
+/*
+ * 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
+ *
+ * https://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 ...;
+```
+
+## Update license header to modified files as necessary
+
+Always check the date range in the Apache license header. For example, if you've modified a file in 2013 whose header still reads
+
+```java
+ * Copyright 2002-2011 the original author or authors.
+```
+
+then be sure to update it to 2013 appropriately
+
+```java
+ * Copyright 2002-2013 the original author or authors.
+```
+
+## Use @since tags
+
+Use @since tags for newly-added public API types and methods e.g.
+
+```java
+/**
+ * ...
+ *
+ * @author First Last
+ * @since 3.0
+ * @see ...
+ */
+```
+
+## Submit JUnit test cases for all behavior changes
+
+Search the codebase to find related unit tests and add additional @Test methods within. It is also acceptable to submit test cases on a per JIRA issue basis.
+
+## Squash commits
+
+Use `git rebase --interactive`, `git add --patch` and other tools to "squash" multiple commits into atomic changes. In addition to the man pages for git, there are many resources online to help you understand how these tools work. Here is one: https://book.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing .
+
+## Use your real name in git commits
+
+Please configure git to use your real first and last name for any commits you intend to submit as pull requests. For example, this is not acceptable:
+
+ Author: Nickname
+
+Rather, please include your first and last name, properly capitalized, as submitted against the Spring contributor license agreement:
+
+ Author: First Last
+
+This helps ensure traceability against the CLA, and also goes a long way to ensuring useful output from tools like `git shortlog` and others.
+
+You can configure this globally via the account admin area GitHub (useful for fork-and-edit cases); globally with
+
+ git config --global user.name "First Last"
+ git config --global user.email user@mail.com
+
+or locally for the *spring-batch repository only by omitting the '--global' flag:
+
+ cd spring-batch
+ git config user.name "First Last"
+ git config user.email user@mail.com
+
+## Run all tests prior to submission
+
+See the [checking out and building][] section of the README for instructions. Make sure that all tests pass prior to submitting your pull request.
+
+## Mention your pull request on the associated JIRA issue
+
+Add a comment to the associated JIRA issue(s) linking to your new pull request.
+
+[help documentation]: https://help.github.com/send-pull-requests
+[JIRA issue tracker]: https://jira.spring.io/browse/BATCH
+[checking out and building]: https://github.com/spring-projects/spring-batch#building-from-source
diff --git a/README.md b/README.md
index e275573f80..d36568450d 100644
--- a/README.md
+++ b/README.md
@@ -1,102 +1,54 @@
-# Spring Batch
+
+
+# Spring Batch [](https://build.spring.io/browse/BATCH-GRAD)
Spring Batch is a lightweight, comprehensive batch framework designed to enable the development of robust batch applications vital for the daily operations of enterprise systems. Spring Batch builds upon the productivity, POJO-based development approach, and general ease of use capabilities people have come to know from the [Spring Framework](https://github.com/SpringSource/spring-framework), while making it easy for developers to access and leverage more advanced enterprise services when necessary.
-If you are looking for a runtime container for your Batch applications, or need a management console to view current and historic executions, take a look at [Spring Batch Admin](http://www.springsource.org/spring-batch-admin). It is a set of services (Java, JSON, JMX) and an optional web UI that you can use to manage and monitor a Batch system.
+If you are looking for a runtime orchestration tool for your Batch applications, or need a management console to view current and historic executions, take a look at [Spring Cloud Data Flow](https://cloud.spring.io/spring-cloud-dataflow/). It is an orchestration tool for deploying and executing data integration based microservices including Spring Batch applications.
# Building from Source
Clone the git repository using the URL on the Github home page:
- $ git clone git://github.com/SpringSource/spring-batch.git
+ $ git clone git@github.com:spring-projects/spring-batch.git
$ cd spring-batch
## Command Line
-Use Maven 2.2 or 3.0, then on the command line:
-
- $ mvn install
-
-or, the first time (to download the stuff that isn't in the Maven Central repository):
+Gradle is the build tool used for Spring Batch. You can perform a full build of Spring Batch via the command:
- $ mvn install -P bootstrap
-
-To perform a full build of all modules (required prior to issuing a pull request) execute the all profile
+ $ ./gradlew build
- $ mvn install -P all
+## Spring Tool Suite (STS)
+In STS (or any Eclipse distro or other IDE with Gradle support), import the module directories as existing projects. They should compile and the tests should run with no additional steps.
-## SpringSource Tool Suite (STS)
-In STS (or any Eclipse distro or other IDE with Maven support), import the module directories as existing projects. They should compile and the tests should run with no additional steps.
+# Getting Started Using Spring Boot
+This is the quickest way to get started with a new Spring Batch project. You find the Getting Started Guide for Spring
+Batch on Spring.io: [Creating a Batch Service](https://spring.io/guides/gs/batch-processing/)
-# Getting Started Using SpringSource Tool Suite (STS)
+# Getting Started Using Spring Tool Suite (STS)
- This is the quickest way to get started. It requires an internet connection for download, and access to a Maven repository (remote or local).
+It requires an internet connection for download, and access to a Maven repository (remote or local).
-* Download STS version 2.5.* (or better) from the [SpringSource website](http://www.springsource.com/products/sts). STS is a free Eclipse bundle with many features useful for Spring developers.
+* Download STS version 3.4.* (or better) from the [Spring website](https://spring.io/tools/sts/). STS is a free Eclipse bundle with many features useful for Spring developers.
* Go to `File->New->Spring Template Project` from the menu bar (in the Spring perspective).
* The wizard has a drop down with a list of template projects. One of them is a "Simple Spring Batch Project". Select it and follow the wizard.
* A project is created with all dependencies and a simple input/output job configuration. It can be run using a unit test, or on the command line (see instructions in the pom.xml).
# Getting Help
-Read the main project [website](http://www.springsource.org/spring-batch) and the [User Guide](http://static.springsource.org/spring-batch/reference). Look at the source code and the Javadocs. For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=41). If you are new to Spring as well as to Spring Batch, look for information about [Spring projects](http://www.springsource.org/projects).
+Read the main project [website](https://projects.spring.io/spring-batch/) and the [User Guide](https://docs.spring.io/spring-batch/trunk/reference/). Look at the source code and the Javadocs. For more detailed questions, use the [forum](https://forum.spring.io/forum/spring-projects/batch). If you are new to Spring as well as to Spring Batch, look for information about [Spring projects](https://spring.io/projects).
# Contributing to Spring Batch
Here are some ways for you to get involved in the community:
-* Get involved with the Spring community on the Spring Community Forums. Please help out on the [forum](http://forum.springsource.org/forumdisplay.php?f=41) by responding to questions and joining the debate.
-* Create [JIRA](https://jira.springsource.org/browse/BATCH) tickets for bugs and new features and comment and vote on the ones that you are interested in.
-* Github is for social coding: if you want to write code, we encourage contributions through pull requests from [forks of this repository](http://help.github.com/forking/). If you want to contribute code this way, please familiarize yourself with the process oulined for contributing to Spring projects here: [Contributor Guidelines](https://github.com/SpringSource/spring-integration/wiki/Contributor-Guidelines).
-* Watch for upcoming articles on Spring by [subscribing](http://www.springsource.org/node/feed) to springframework.org
+* Get involved with the Spring community on the Spring Community Forums. Please help out on the [forum](https://forum.spring.io/forum/spring-projects/batch) by responding to questions and joining the debate.
+* Create [JIRA](https://jira.spring.io/browse/BATCH) tickets for bugs and new features and comment and vote on the ones that you are interested in.
+* Github is for social coding: if you want to write code, we encourage contributions through pull requests from [forks of this repository](https://help.github.com/forking/). If you want to contribute code this way, please familiarize yourself with the process outlined for contributing to Spring projects here: [Contributor Guidelines](https://github.com/spring-projects/spring-batch/blob/master/CONTRIBUTING.md).
+* Watch for upcoming articles on Spring by [subscribing](feed://assets.spring.io/drupal/node/feed.xml) to spring.io
Before we accept a non-trivial patch or pull request we will need you to sign the [contributor's agreement](https://support.springsource.com/spring_committer_signup). Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.
-
-# Getting Started Using the Samples
-
-A convenient way to get started quickly with Spring Batch is to run the samples which are packaged in the samples module. There is also a simple command line sample (or "archetype") which has a bare bones but complete implementation of a simpel job. The source code for the samples (and the other modules) is available either from the [Zip assembly](http://static.springsource.org/spring-batch/downloads.html) or from [Git](http://www.springsource.org/spring-batch/source-repository.html).
-
-## Using the .Zip Distribution
-
-### With Maven and Eclipse
-
-* Download the "no-dependencies" version of the distribution and unzip to create a directory `org.springframework.batch-.
-* Get the [m2eclipse plugin](http://m2eclipse.sonatype.org/update)
- (installed in STS out of the box). If you can't or don't want to
- install this plugin, you can use the [Maven Eclipse
- Plugin](http://maven.apache.org/plugins/maven-eclipse-plugin) to
- create the classpath entries you need.
-* Open Eclipse and create a workspace as for the non-Mavenized version.
-* Import the samples and archetype projects from the samples sub-directory in the directory you just unpacked.
-* The project should build cleanly without having to fix the dependencies. If it doesn't, make sure you are online, and maybe try building on the command line first to make sure all the dependencies are downloaded. See the [build instructions](http://static.springsource.org/spring-batch/building.html) if you run into difficulty.
-
-(N.B. the "archetype" is not a real Maven archetype, just a template project that can be used as a starting point for a self-contained batch job. It is the same project that can be imported into STS using the Project Template wizard.)
-
-### With Maven on the Command Line
-
-* Download the distribution as above.
-* Then run Maven in the spring-batch-samples directory, e.g.
-
- $ cd spring-batch-samples
- $ mvn test
- ...
-
-### With Eclipse and without Maven
-
-Similar instructions would apply to other IDEs.
-
-* Download the "no-dependencies" package and unzip to create a directory `spring-batch-.
-* Open Eclipse and make a workspace in the directory you just created.
-* Import the `org.springframework.batch.samples` project from the samples directory.
-* Find all the compile scope and non-optional runtime jar files listed in the [core dependencies report](http://static.springsource.org/spring-batch/spring-batch-core/dependencies.html) and [infrastructure dependencies](http://static.springsource.org/spring-batch/spring-batch-infrastructure/dependencies.html), and import them into the project.
-* Force the workspace to build (e.g. Project -> Clean...)
-* Run the unit tests in your project under src/test/java. N.B. the FootbalJobFunctionTests takes quite a long time to run.
-
-You can get a pretty good idea about how to set up a job by examining the unit tests in the `org.springframework.batch.sample` package (in `src/main/java`) and the configuration in `src/main/resources/jobs`.
-
-To launch a job from the command line instead of a unit test use the `CommandLineJobRunner.main()` method (see Javadocs included in that class).
-
-## Using Maven and Git
-
-* Check out the Spring Batch project from Git (instructions are available [here](https://github.com/SpringSource/spring-batch)).
-* Run Maven from the command line in the samples directory. There are additional building instructions and suggestions about what to do if it goes wrong [here](http://static.springsource.org/spring-batch/building.html).
+# Code of Conduct
+ This project adheres to the [Contributor Covenant ](https://github.com/spring-projects/spring-batch/blob/master/CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
+
\ No newline at end of file
diff --git a/archetypes/common-test.xml b/archetypes/common-test.xml
deleted file mode 100644
index cc38edb16e..0000000000
--- a/archetypes/common-test.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
deleted file mode 100644
index 03f12915db..0000000000
--- a/archetypes/pom.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- 4.0.0
- spring-batch-archetype
- pom
- Archetypes
- http://static.springframework.org/spring-batch/${artifactId}
- Spring Batch archetypes are simple project templates containing just enough code to get you started running a job. For more detailed examples of using particular features of the framework, look at the Spring Batch Samples project. Currently the archetypes are deployed as regular Maven projects (not archetypes), because of limitations in the archetype plugin (or our understanding of how it works). For most effective use, copy one into Eclipse and use Q4E to manage the dependencies.
-
- org.springframework.batch
- spring-batch-parent
- 2.2.2.BUILD-SNAPSHOT
- ../spring-batch-parent
-
-
- simple-cli
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- junit:junit
-
-
-
-
-
-
diff --git a/archetypes/simple-cli/.springBeans b/archetypes/simple-cli/.springBeans
deleted file mode 100644
index f2c1c7d8a4..0000000000
--- a/archetypes/simple-cli/.springBeans
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- 1
-
-
-
-
-
-
- src/test/resources/test-context.xml
- src/main/resources/META-INF/spring/module-context.xml
- src/main/resources/launch-context.xml
-
-
-
-
diff --git a/archetypes/simple-cli/pom.xml b/archetypes/simple-cli/pom.xml
deleted file mode 100644
index 3d3a0e7a82..0000000000
--- a/archetypes/simple-cli/pom.xml
+++ /dev/null
@@ -1,286 +0,0 @@
-
-
- 4.0.0
- org.springframework.batch
- spring-batch-simple-cli
- 2.2.2.BUILD-SNAPSHOT
- jar
- Commandline
- http://www.springframework.org/spring-batch/archetypes/simple-cli-archetype
- 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.
-
-
- 3.2.0.RELEASE
- 2.2.2.BUILD-SNAPSHOT
- false
- 4.10
- 1.6
- 1.6
- UTF-8
-
-
-
- staging
-
-
- staging
- file:///${user.dir}/target/staging
-
-
- staging
- file:///${user.dir}/target/staging
-
-
-
-
- bootstrap
-
-
- Codehaus
- http://repository.codehaus.org/
-
- false
-
-
-
- com.springsource.repository.bundles.release
- SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases
- http://repository.springsource.com/maven/bundles/release
-
- false
-
-
-
-
-
-
-
- junit
- junit
- ${junit.version}
- test
-
-
- org.springframework
- spring-test
- ${spring.framework.version}
- test
-
-
- org.springframework
- spring-aop
- ${spring.framework.version}
-
-
- org.springframework
- spring-jdbc
- ${spring.framework.version}
-
-
- org.springframework.batch
- spring-batch-core
- ${spring.batch.version}
-
-
- org.springframework.batch
- spring-batch-infrastructure
- ${spring.batch.version}
-
-
- org.springframework.batch
- spring-batch-test
- ${spring.batch.version}
- test
-
-
- commons-dbcp
- commons-dbcp
- 1.2.2
-
-
- org.slf4j
- slf4j-log4j12
- 1.5.8
- true
-
-
- log4j
- log4j
- 1.2.14
- true
-
-
- commons-io
- commons-io
- 1.4
-
-
- org.hsqldb
- hsqldb
- 2.2.9
-
-
- org.aspectj
- aspectjrt
- 1.6.8
-
-
- org.aspectj
- aspectjweaver
- 1.6.8
-
-
-
-
-
- org.springframework.build.aws
- org.springframework.build.aws.maven
- 3.0.0.RELEASE
-
-
-
-
-
- maven-assembly-plugin
- false
-
-
- project
-
-
-
-
-
- org.eclipse.m2e
- lifecycle-mapping
- 1.0.0
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
- [1.0,)
-
- copy-dependencies
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
-
- ${compiler.source.version}
- ${compiler.target.version}
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- **/*Tests.java
-
-
- **/Abstract*.java
-
- junit:junit
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
- 1.1
-
- org.springframework.batch.core.launch.support.CommandLineJobRunner
-
- classpath:/launch-context.xml
- personJob
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- package
-
- copy-dependencies
-
-
- ${project.build.directory}/lib
-
-
-
-
-
- maven-assembly-plugin
- 2.3
-
-
- src/main/assembly/descriptor.xml
-
-
-
-
- make-distribution
- package
-
- single
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
- false
-
- org.springframework.batch.core.launch.support.CommandLineJobRunner
- true
- lib/
-
-
-
-
-
-
-
- http://www.springframework.org/download
-
- staging
- file:///${user.dir}/target/staging/org.springframework.batch.archetype/${project.artifactId}
-
-
- spring-release
- Spring Release Repository
- file:///${user.dir}/target/staging/release
-
-
- spring-snapshot
- Spring Snapshot Repository
- file:///${user.dir}/target/staging/snapshot
-
-
-
diff --git a/archetypes/simple-cli/src/main/assembly/descriptor.xml b/archetypes/simple-cli/src/main/assembly/descriptor.xml
deleted file mode 100644
index c28873cb29..0000000000
--- a/archetypes/simple-cli/src/main/assembly/descriptor.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
- distribution
-
- tar.gz
-
- false
-
-
- src/main/scripts
- bin
- true
-
-
- src/main/resources
- resources
- true
- true
-
-
-
-
- lib
-
-
-
diff --git a/archetypes/simple-cli/src/main/java/example/Person.java b/archetypes/simple-cli/src/main/java/example/Person.java
deleted file mode 100644
index 43787449db..0000000000
--- a/archetypes/simple-cli/src/main/java/example/Person.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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;
-
-/**
- *
- * Domain object representing information about a person.
- *
- */
-public class Person {
- private String lastName;
- private String firstName;
-
- 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;
- }
-}
diff --git a/archetypes/simple-cli/src/main/java/example/PersonItemProcessor.java b/archetypes/simple-cli/src/main/java/example/PersonItemProcessor.java
deleted file mode 100644
index b9a25bdeab..0000000000
--- a/archetypes/simple-cli/src/main/java/example/PersonItemProcessor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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;
-
-/**
- *
- * An example {@link org.springframework.batch.item.ItemProcessor} implementation that upper cases attributes on the
- * provided {@link Person} object.
- *
- */
-public class PersonItemProcessor implements ItemProcessor {
- @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;
- }
-}
diff --git a/archetypes/simple-cli/src/main/resources/META-INF/spring/module-context.xml b/archetypes/simple-cli/src/main/resources/META-INF/spring/module-context.xml
deleted file mode 100644
index 4d20c2fe7f..0000000000
--- a/archetypes/simple-cli/src/main/resources/META-INF/spring/module-context.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Example job providing a skeleton for a typical batch application.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archetypes/simple-cli/src/main/resources/batch.properties b/archetypes/simple-cli/src/main/resources/batch.properties
deleted file mode 100644
index dea386513f..0000000000
--- a/archetypes/simple-cli/src/main/resources/batch.properties
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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
diff --git a/archetypes/simple-cli/src/main/resources/launch-context.xml b/archetypes/simple-cli/src/main/resources/launch-context.xml
deleted file mode 100644
index f47c948ced..0000000000
--- a/archetypes/simple-cli/src/main/resources/launch-context.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archetypes/simple-cli/src/main/resources/log4j.properties b/archetypes/simple-cli/src/main/resources/log4j.properties
deleted file mode 100644
index 2cdeeb81ba..0000000000
--- a/archetypes/simple-cli/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-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
diff --git a/archetypes/simple-cli/src/main/resources/support/person.sql b/archetypes/simple-cli/src/main/resources/support/person.sql
deleted file mode 100644
index 4e405e6de6..0000000000
--- a/archetypes/simple-cli/src/main/resources/support/person.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-DROP TABLE people IF EXISTS;
-
-CREATE TABLE people (
- person_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
- first_name VARCHAR(20),
- last_name VARCHAR(20)
-);
diff --git a/archetypes/simple-cli/src/main/scripts/runJob.bat b/archetypes/simple-cli/src/main/scripts/runJob.bat
deleted file mode 100644
index 72ed089a47..0000000000
--- a/archetypes/simple-cli/src/main/scripts/runJob.bat
+++ /dev/null
@@ -1,8 +0,0 @@
-@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
diff --git a/archetypes/simple-cli/src/main/scripts/runJob.sh b/archetypes/simple-cli/src/main/scripts/runJob.sh
deleted file mode 100644
index fe9e1c8bdd..0000000000
--- a/archetypes/simple-cli/src/main/scripts/runJob.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/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
diff --git a/archetypes/simple-cli/src/site/site.xml b/archetypes/simple-cli/src/site/site.xml
deleted file mode 100644
index 42b3b297eb..0000000000
--- a/archetypes/simple-cli/src/site/site.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- Spring Batch: ${project.name}
- index.html
-
-
-
- org.springframework.maven.skins
- maven-spring-skin
- 1.0.5
-
-
-
-
-
-
-
-
-
diff --git a/archetypes/simple-cli/src/test/java/example/PersonItemProcessorTest.java b/archetypes/simple-cli/src/test/java/example/PersonItemProcessorTest.java
deleted file mode 100644
index 49f0d3da03..0000000000
--- a/archetypes/simple-cli/src/test/java/example/PersonItemProcessorTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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;
-
-/**
- *
- * Example test case processing a {@link Person} using the {@link PersonItemProcessor}.
- *
- */
-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());
- }
-}
diff --git a/archetypes/simple-cli/src/test/java/example/PersonJobConfigurationTest.java b/archetypes/simple-cli/src/test/java/example/PersonJobConfigurationTest.java
deleted file mode 100644
index 96fbf4cce8..0000000000
--- a/archetypes/simple-cli/src/test/java/example/PersonJobConfigurationTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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;
-
-/**
- *
- * Test cases asserting on the example job's configuration.
- *
merging - Contains the projects being merged into this project
+ *
runtimeMerge - Contains all dependencies that are merge projects. These are used
+ * to allow an IDE to reference merge projects.
+ *
+ *
+ * @author Rob Winch
+ * @author Phillip Webb
+ */
+class MergePlugin implements Plugin {
+
+ private static boolean attachedProjectsEvaluated;
+
+ public void apply(Project project) {
+ project.plugins.apply(MavenPlugin)
+ project.plugins.apply(EclipsePlugin)
+ project.plugins.apply(IdeaPlugin)
+
+ MergeModel model = project.extensions.create("merge", MergeModel)
+ project.configurations.create("merging")
+ Configuration runtimeMerge = project.configurations.create("runtimeMerge")
+
+ // Ensure the IDE can reference merged projects
+ project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
+ project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
+
+ // Hook to perform the actual merge logic
+ project.afterEvaluate{
+ if (it.merge.into != null) {
+ setup(it)
+ }
+ }
+
+ // Hook to build runtimeMerge dependencies
+ if (!attachedProjectsEvaluated) {
+ project.gradle.projectsEvaluated{
+ postProcessProjects(it)
+ }
+ attachedProjectsEvaluated = true;
+ }
+ }
+
+ private void setup(Project project) {
+ project.merge.into.dependencies.add("merging", project)
+ project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
+ project.dependencies.add("runtimeMerge", project.merge.into)
+ setupTaskDependencies(project)
+ setupMaven(project)
+ }
+
+ private void setupTaskDependencies(Project project) {
+ // invoking a task will invoke the task with the same name on 'into' project
+ ["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
+ def task = project.tasks.findByPath(it)
+ if (task) {
+ task.enabled = false
+ task.dependsOn(project.merge.into.tasks.findByPath(it))
+ }
+ }
+
+ // update 'into' project artifacts to contain the source artifact contents
+ project.merge.into.sourcesJar.from(project.sourcesJar.source)
+ project.merge.into.jar.from(project.sourceSets.main.output)
+ project.merge.into.javadoc {
+ source += project.javadoc.source
+ classpath += project.javadoc.classpath
+ }
+ }
+
+ private void setupMaven(Project project) {
+ project.configurations.each { configuration ->
+ Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
+ if (mapping.scope) {
+ Configuration intoConfiguration = project.merge.into.configurations.create(
+ project.name + "-" + configuration.name)
+ configuration.excludeRules.each {
+ configuration.exclude([
+ (ExcludeRule.GROUP_KEY) : it.group,
+ (ExcludeRule.MODULE_KEY) : it.module])
+ }
+ configuration.dependencies.each {
+ def intoCompile = project.merge.into.configurations.getByName("compile")
+ // Protect against changing a compile scope dependency (SPR-10218)
+ if (!intoCompile.dependencies.contains(it)) {
+ intoConfiguration.dependencies.add(it)
+ }
+ }
+ def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
+ project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
+ mapping.priority + 100 + index, intoConfiguration, mapping.scope)
+ }
+ }
+ }
+
+ private postProcessProjects(Gradle gradle) {
+ gradle.rootProject.subprojects(new Action() {
+ public void execute(Project project) {
+ project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
+ Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
+ dependsOnMergedFrom.dependencies.each{ dep ->
+ project.dependencies.add("runtimeMerge", dep.dependencyProject)
+ }
+ }
+ }
+ });
+ }
+}
+
+class MergeModel {
+ Project into;
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/merge.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/merge.properties
new file mode 100644
index 0000000000..9cef804165
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/merge.properties
@@ -0,0 +1 @@
+implementation-class=org.springframework.build.gradle.MergePlugin
diff --git a/dictionary.txt b/dictionary.txt
index 63e4bda797..9aba8f63e9 100644
--- a/dictionary.txt
+++ b/dictionary.txt
@@ -99,3 +99,215 @@ accessors
subclassing
ajax
javascript
+chris
+schaefer
+unescaped
+namespace
+autowired
+registrar
+ref
+configurer
+callable
+classpath
+config
+registries
+stephane
+nicoll
+href
+fischer
+sebastien
+gerard
+xml
+gt
+garrette
+thomas
+risberg
+josh
+preconfigured
+lob
+hydrated
+hydrate
+subflow
+validator
+subflows
+wildcard
+foo
+wildcards
+pre
+morten
+andersen
+gott
+validators
+enum
+init
+elvis
+refactored
+autowire
+batchlet
+upfront
+glenn
+renfro
+arg
+chunking
+spec
+honour
+ids
+exiter
+stdin
+stijn
+maller
+schipp
+javadocs
+prioritising
+recognise
+summarise
+summarising
+analyse
+no-op
+multicaster
+optimisation
+deserializes
+david
+turanski
+serializer
+multi
+charsets
+jettison
+deserialization
+jimmy
+praet
+behaviour
+unregistration
+initialised
+hydrating
+aop
+analysed
+ignorable
+tarred
+generics
+memorise
+modularise
+skippability
+panicking
+eric
+evans
+deserialize
+wonky
+rawtypes
+internet
+inline
+foobar
+sergey
+shcherbakov
+jsr
+blah
+txt
+spam
+punk
+min
+downgrade
+weirdnesses
+varchar
+warmup
+tobias
+flohre
+backstop
+timestamp
+recognised
+attrs
+ouch
+tripped
+barf
+baz
+phil
+webb
+costin
+leau
+hsql
+vs
+payload
+mongo
+cypher
+iterable
+anatoly
+polinsky
+sybase
+thexton
+postgres
+luke
+taylor
+rowid
+num
+externalized
+juergen
+hoeller
+capitalised
+capitalisation
+tokenization
+tomas
+slanina
+tokenizing
+alef
+arjen
+arendsen
+poutsma
+levenshtein
+unset
+unparseable
+tokenizers
+parseable
+regex
+customisation
+waseem
+malik
+synced
+charset
+juliusz
+brzostek
+marshallers
+unmarshaller
+marshaller
+uri
+namespaces
+xmlns
+woodstox
+inits
+marshalled
+precache
+douglas
+kaminsky
+endeavour
+uncategorised
+specialisation
+tenuous
+checkpointing
+mutex
+signalling
+customise
+rethrowing
+queueing
+runnables
+resourceless
+initialisation
+args
+params
+delegator
+val
+asc
+desc
+unmarshalling
+unmarshallers
+resettable
+dataset
+signalled
+injectable
+asynch
+flakey
+usecase
+tokenize
+debit
+isin
+fieldsets
+mockito
+mappers
+adhoc
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000000..6acf520a9d
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+version=4.2.0.RELEASE
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..28861d273a
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..ae45383b6d
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000000..4453ccea33
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100755
index 0000000000..e95643d6a2
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index a0355621f4..0000000000
--- a/pom.xml
+++ /dev/null
@@ -1,652 +0,0 @@
-
-
- 4.0.0
- org.springframework.batch
- spring-batch
- Spring Batch
- Spring Batch provides tools for enterprise batch or bulk processing. It can be used to wire up jobs, and track
- their execution, or simply as an optimization for repetitive processing in a transactional environment. Spring Batch is part of the Spring Portfolio.
- 2.2.2.BUILD-SNAPSHOT
- pom
-
- spring-batch-parent
- spring-batch-infrastructure
- spring-batch-core
- spring-batch-test
-
- http://www.springsource.org/spring-batch
-
- SpringSource
- http://www.springsource.com
-
-
- http://github.com/SpringSource/spring-batch
- scm:git:git://github.com/SpringSource/spring-batch.git
- scm:git:ssh://git@github.com/SpringSource/spring-batch.git
- HEAD
-
-
- JIRA
- http://opensource.atlassian.com/projects/spring/browse/BATCH
-
-
-
- Spring Batch Forum
- http://forum.springframework.org/forumdisplay.php?f=41
- http://forum.springframework.org/forumdisplay.php?f=41
-
-
-
- Bamboo
- https://build.springframework.org/bamboo/browse/BATCH
-
-
-
- Apache 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
-
-
-
- UTF-8
- false
- spring-batch
- Spring Batch
- BATCH
- ${project.version}
- ${dist.id}-${dist.version}-no-dependencies
- ${dist.finalName}.zip
- target/${dist.fileName}
- dist.springframework.org
-
-
-
- all
-
- spring-batch-samples
- archetypes
- spring-batch-infrastructure-tests
- spring-batch-core-tests
-
-
-
- release
-
- spring-batch-samples
- archetypes
-
-
-
-
- maven-assembly-plugin
- false
-
-
- zip-files
- false
- package
-
- single
-
-
-
- src/assembly/no-dependencies.xml
-
-
-
-
-
-
- com.agilejava.docbkx
- docbkx-maven-plugin
- 2.0.8
-
-
- single-page
-
- generate-html
-
-
- ${basedir}/src/docbkx/resources/xsl/html.xsl
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pre-site
-
-
- single-pdf
-
- generate-pdf
-
-
- src/site/docbook/reference/
- src/docbkx/resources/images/
-
-
-
-
- pre-site
-
-
- multi-page
-
- generate-html
-
-
- true
- ${basedir}/src/docbkx/resources/xsl/html_chunk.xsl
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pre-site
-
-
-
-
- org.docbook
- docbook-xml
- 4.4
- runtime
-
-
- org.apache.xmlgraphics
- fop
- 0.93
-
-
-
- index.xml
- false
-
- css/html.css
- ${basedir}/src/site/docbook/reference
- ${basedir}/src/docbkx/resources/xsl/fopdf.xsl
- true
-
-
- version
- ${project.version}
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
- copy-parent-pom
- generate-sources
-
-
-
-
-
-
- run
-
-
-
- upload-dist
- deploy
-
- run
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- verify
-
- false
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
- extract
- verify
-
- run
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-invoker-plugin
-
- target/it/no-dep
- target/local-repo
- true
- ${basedir}/src/it/settings.xml
-
- test
-
-
- samples/*/pom.xml
-
-
-
-
- integration-test
- verify
-
- run
-
-
-
-
-
-
-
-
- build
-
- false
-
-
-
-
-
- org.apache.maven.plugins
- maven-invoker-plugin
-
- ${basedir}
- target/local-repo
- true
- ${basedir}/src/it/settings.xml
-
- clean
- install
-
-
- pom.xml
-
-
-
-
- integration-test
- verify
-
- run
-
-
-
-
-
-
-
-
- samples
-
- spring-batch-samples
- archetypes
-
-
-
- milestone
-
-
- spring-milestone
- Spring Milestone Repository
- s3://maven.springframework.org/milestone
-
-
-
-
- central
-
-
- sonatype-nexus-snapshots
- Sonatype Nexus Snapshots
- https://oss.sonatype.org/content/repositories/snapshots/
-
-
- sonatype-nexus-staging
- Nexus Release Repository
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
-
-
-
-
- staging
-
- /${user.dir}/target/staging/dist
-
-
-
- staging
- file:///${user.dir}/target/staging
-
-
- staging
- file:///${user.dir}/target/staging
-
-
- staging
- file:///${user.dir}/target/staging
-
-
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
-
- false
-
-
-
-
- ${dist.finalName}
-
-
-
- manifest
-
- false
-
-
-
-
- com.springsource.bundlor
- com.springsource.bundlor.maven
-
-
- bundlor-manifest
- package
-
- manifest
-
-
-
-
-
-
-
-
-
-
- static.springframework.org
- scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-batch/trunk
-
-
- spring-release
- Spring Release Repository
- s3://maven.springframework.org/release
-
-
- spring-snapshot
- Spring Snapshot Repository
- s3://maven.springframework.org/snapshot
-
-
-
-
-
- org.springframework.build.aws
- org.springframework.build.aws.maven
- 3.0.0.RELEASE
-
-
-
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.3
-
-
- org.apache.maven.plugins
- maven-site-plugin
- 2.2
-
-
- org.apache.maven.wagon
- wagon-ssh
- 1.0-beta-7
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
- 1.4
-
-
- org.springframework.build
- org.springframework.build.aws.ant
- 3.0.5.RELEASE
-
-
- net.java.dev.jets3t
- jets3t
- 0.7.2
-
-
- org.apache.ant
- ant
- 1.7.0
-
-
- org.apache.ant
- ant-apache-regexp
- 1.7.0
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- junit:junit
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
- 2.7
-
- true
-
-
-
-
-
- true
-
-
- org.apache.maven.plugins
- maven-project-info-reports-plugin
- 2.1.1
-
-
- org.apache.maven.plugins
- maven-surefire-report-plugin
- 2.3
-
-
- org.codehaus.mojo
- jdepend-maven-plugin
- 2.0-beta-2
-
-
- maven-javadoc-plugin
- 2.8.1
-
-
- html
-
- javadoc
-
-
-
-
- true
- true
-
- http://download.oracle.com/javaee/5/api
- http://download.oracle.com/javase/1.5.0/docs/api
- http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/
- http://jakarta.apache.org/commons/dbcp/apidocs/
- http://jakarta.apache.org/commons/fileupload/apidocs/
- http://jakarta.apache.org/commons/httpclient/apidocs/
- http://jakarta.apache.org/commons/pool/apidocs/
- http://jakarta.apache.org/commons/logging/apidocs/
- http://junit.sourceforge.net/javadoc/
- http://logging.apache.org/log4j/docs/api/
- http://jakarta.apache.org/regexp/apidocs/
- http://jakarta.apache.org/velocity/api/
- http://static.springsource.org/spring/docs/3.1.2.RELEASE/javadoc-api/
- http://static.springframework.org/spring-batch/apidocs/
- http://static.springframework.org/spring-ws/site/apidocs/
-
- test.*:*.example:*.sample
-
-
-
- org.apache.maven.plugins
- maven-jxr-plugin
- 2.3
-
-
-
-
-
- dsyer
- Dave Syer
- david.syer@springsource.com
-
-
- nebhale
- Ben Hale
- ben.hale@springsource.com
- 0
-
-
- lward
- Lucas Ward
- lucas.l.ward@accenture.com
-
-
- robokaso
- Robert Kasanicky
- robokaso@gmail.com
-
-
- trisberg
- Thomas Risberg
- thomas.risberg@springsource.com
-
-
- dhgarrette
- Dan Garrette
- dhgarrette@gmail.com
-
-
- mminella
- Michael Minella
- mminella@vmware.com
-
-
-
-
- com.springsource.repository.bundles.milestone
- SpringSource Enterprise Bundle Repository - SpringSource Bundle Milestones
- http://repository.springsource.com/maven/bundles/milestone
-
- false
-
-
-
- com.springsource.repository.bundles.snapshot
- SpringSource Enterprise Bundle Repository - SpringSource Bundle Snapshots
- http://repository.springsource.com/maven/bundles/snapshot
-
-
- com.springsource.repository.bundles.release
- SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases
- http://repository.springsource.com/maven/bundles/release
-
- false
-
-
-
-
diff --git a/publish-maven.gradle b/publish-maven.gradle
new file mode 100644
index 0000000000..6c3625aa0d
--- /dev/null
+++ b/publish-maven.gradle
@@ -0,0 +1,94 @@
+apply plugin: "propdeps-maven"
+
+install {
+ repositories.mavenInstaller {
+ customizePom(pom, project)
+ }
+}
+
+def customizePom(pom, gradleProject) {
+ pom.whenConfigured { generatedPom ->
+
+ // eliminate test-scoped dependencies (no need in maven central poms)
+ generatedPom.dependencies.removeAll { dep ->
+ dep.scope == 'test'
+ }
+
+ // sort to make pom dependencies order consistent to ease comparison of older poms
+ generatedPom.dependencies = generatedPom.dependencies.sort { dep ->
+ "$dep.scope:$dep.groupId:$dep.artifactId"
+ }
+
+ // add all items necessary for maven central publication
+ generatedPom.project {
+ name = gradleProject.description
+ description = gradleProject.description
+ url = linkHomepage
+ organization {
+ name = 'Spring'
+ url = 'https://spring.io/'
+ }
+ licenses {
+ license {
+ name 'The Apache Software License, Version 2.0'
+ url 'https://www.apache.org/licenses/LICENSE-2.0.txt'
+ distribution 'repo'
+ }
+ }
+
+ scm {
+ url = linkScmUrl
+ connection = 'scm:git:' + linkScmConnection
+ developerConnection = 'scm:git:' + linkScmDevConnection
+ }
+
+ developers {
+ developer {
+ id = 'dsyer'
+ name = 'Dave Syer'
+ email = 'dsyer@pivotal.io'
+ }
+ developer {
+ id = 'nebhale'
+ name = 'Ben Hale'
+ email = 'bhale@gpivotal.io'
+ }
+ developer {
+ id = 'lward'
+ name = 'Lucas Ward'
+ }
+ developer {
+ id = 'robokaso'
+ name = 'Robert Kasanicky'
+ email = 'robokaso@gmail.com'
+ }
+ developer {
+ id = 'trisberg'
+ name = 'Thomas Risberg'
+ email = 'trisberg@pivotal.io'
+ }
+ developer {
+ id = 'dhgarrette'
+ name = 'Dan Garrette'
+ email = 'dhgarrette@gmail.com'
+ }
+ developer {
+ id = 'mminella'
+ name = 'Michael Minella'
+ email = 'mminella@pivotal.io'
+ roles = ["project lead"]
+ }
+ developer {
+ id = 'chrisjs'
+ name = 'Chris Schaefer'
+ email = 'cschaefer@pivotal.io'
+ }
+ developer {
+ id = 'benas'
+ name = 'Mahmoud Ben Hassine'
+ email = 'mbenhassine@pivotal.io'
+ }
+ }
+ }
+ }
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000..8cf9aadd38
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,13 @@
+rootProject.name = 'spring-batch'
+
+include 'spring-batch-core'
+include 'spring-batch-core-tests'
+include 'spring-batch-docs'
+include 'spring-batch-infrastructure'
+include 'spring-batch-infrastructure-tests'
+include 'spring-batch-test'
+include 'spring-batch-integration'
+include 'spring-batch-samples'
+
+include "buildSrc"
+rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
diff --git a/spring-batch-core-tests/.springBeans b/spring-batch-core-tests/.springBeans
index 5f141c431d..b4afd61c9f 100644
--- a/spring-batch-core-tests/.springBeans
+++ b/spring-batch-core-tests/.springBeans
@@ -1,240 +1,299 @@
-
-
- 1
-
-
-
-
-
-
- src/test/resources/data-source-context.xml
- src/test/resources/simple-job-launcher-context.xml
- src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
- true
- false
-
-
-
-
-
+
+
+ 1
+
+
+
+
+
+
+ src/test/resources/data-source-context.xml
+ src/test/resources/simple-job-launcher-context.xml
+ src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml
+ src/main/resources/META-INF/batch/footballJob.xml
+ src/main/resources/META-INF/batch/footballSkipJob.xml
+ src/main/resources/META-INF/batch/parallelJob.xml
+ src/main/resources/META-INF/batch/timeoutJob.xml
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
diff --git a/spring-batch-core-tests/pom.xml b/spring-batch-core-tests/pom.xml
deleted file mode 100644
index 67f418a9df..0000000000
--- a/spring-batch-core-tests/pom.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
- 4.0.0
- spring-batch-core-tests
- Core Tests
- Integration tests for the Spring Batch Core
- http://static.springframework.org/spring-batch/${project.artifactId}
-
- org.springframework.batch
- spring-batch-parent
- 2.2.2.BUILD-SNAPSHOT
- ../spring-batch-parent
-
-
-
- default
-
- true
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- true
-
-
-
-
-
-
- test
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
- job.commit.interval
- 100
-
-
- games.file.name
- games.csv
-
-
- player.file.name
- player.csv
-
-
- ENVIRONMENT
- ${environment}
-
-
-
-
-
-
-
-
- derby
-
- derby
-
-
-
-
-
- org.springframework.batch
- spring-batch-core
- ${project.version}
-
-
- commons-dbcp
- commons-dbcp
-
-
- org.hsqldb
- hsqldb
-
-
- mysql
- mysql-connector-java
- 5.1.6
- runtime
-
-
- postgresql
- postgresql
- 8.3-603.jdbc3
- true
- runtime
-
-
- commons-io
- commons-io
- test
-
-
- org.apache.derby
- derby
-
-
- junit
- junit
-
-
-
-
-
-
- log4j
- log4j
- test
-
-
- org.springframework
- spring-jdbc
-
-
- org.springframework.retry
- spring-retry
-
-
- org.springframework
- spring-test
- test
-
-
- org.springframework
- spring-tx
-
-
- org.springframework
- spring-aop
-
-
- org.aspectj
- aspectjrt
- true
-
-
- org.aspectj
- aspectjweaver
- true
-
-
- cglib
- cglib-nodep
- true
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- junit:junit
-
-
-
-
-
-
- hsql
-
-
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Game.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Game.java
index 1f74b2c581..2624ae6b5a 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Game.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Game.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -18,6 +18,7 @@
import java.io.Serializable;
+@SuppressWarnings("serial")
public class Game implements Serializable {
private String id;
@@ -260,6 +261,7 @@ public void setTotalTd(int totalTd) {
this.totalTd = totalTd;
}
+ @Override
public String toString() {
return "Game: ID=" + id + " " + team + " vs. " + opponent + " - " + year;
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Player.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Player.java
index 5314be5bae..53616e6437 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Player.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/Player.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -18,6 +18,7 @@
import java.io.Serializable;
+@SuppressWarnings("serial")
public class Player implements Serializable {
private String id;
@@ -27,6 +28,7 @@ public class Player implements Serializable {
private int birthYear;
private int debutYear;
+ @Override
public String toString() {
return "PLAYER:id=" + id + ",Last Name=" + lastName +
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerDao.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerDao.java
index 5fedace708..7ca29d0d3d 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerDao.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerDao.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerSummary.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerSummary.java
index 2d906a5dd8..089623564f 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerSummary.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/football/PlayerSummary.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -113,6 +113,7 @@ public void setTotalTd(int totalTd) {
}
+ @Override
public String toString() {
return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards +
";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions +
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java
new file mode 100644
index 0000000000..fe2a6d3b7b
--- /dev/null
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 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
+ *
+ * https://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.core.test.timeout;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.batch.item.ItemWriter;
+
+public class LoggingItemWriter implements ItemWriter {
+
+ protected Log logger = LogFactory.getLog(LoggingItemWriter.class);
+
+ @Override
+ public void write(List extends T> items) throws Exception {
+ logger.info(items);
+ }
+
+}
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java
new file mode 100644
index 0000000000..e801bf37f7
--- /dev/null
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-2019 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
+ *
+ * https://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.core.test.timeout;
+
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.lang.Nullable;
+
+public class SleepingItemProcessor implements ItemProcessor {
+
+ private long millisToSleep;
+
+ @Nullable
+ @Override
+ public I process(I item) throws Exception {
+ Thread.sleep(millisToSleep);
+ return item;
+ }
+
+ public void setMillisToSleep(long millisToSleep) {
+ this.millisToSleep = millisToSleep;
+ }
+
+}
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java
new file mode 100644
index 0000000000..037ea7ee3d
--- /dev/null
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014-2019 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
+ *
+ * https://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.core.test.timeout;
+
+import org.springframework.batch.core.StepContribution;
+import org.springframework.batch.core.scope.context.ChunkContext;
+import org.springframework.batch.core.step.tasklet.Tasklet;
+import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.lang.Nullable;
+
+public class SleepingTasklet implements Tasklet {
+
+ private long millisToSleep;
+
+ @Nullable
+ @Override
+ public RepeatStatus execute(StepContribution contribution,
+ ChunkContext chunkContext) throws Exception {
+ Thread.sleep(millisToSleep);
+ return RepeatStatus.FINISHED;
+ }
+
+ public void setMillisToSleep(long millisToSleep) {
+ this.millisToSleep = millisToSleep;
+ }
+
+}
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java
index a1ff7afcbb..420dd450d5 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -26,6 +26,7 @@ public class FootballExceptionHandler implements ExceptionHandler {
private static final Log logger = LogFactory
.getLog(FootballExceptionHandler.class);
+ @Override
public void handleException(RepeatContext context, Throwable throwable)
throws Throwable {
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java
index 197d4f5251..e2b767ff81 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -22,6 +22,7 @@
public class GameFieldSetMapper implements FieldSetMapper {
+ @Override
public Game mapFieldSet(FieldSet fs) {
if(fs == null){
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java
index 2e8e48ef41..a3b76bac75 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -29,6 +29,7 @@ public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter {
private SimpleJdbcInsert insertGame;
+ @Override
protected void initDao() throws Exception {
super.initDao();
insertGame = new SimpleJdbcInsert(getDataSource()).withTableName("GAMES").usingColumns("player_id", "year_no",
@@ -36,6 +37,7 @@ protected void initDao() throws Exception {
"rushes", "rush_yards", "receptions", "receptions_yards", "total_td");
}
+ @Override
public void write(List extends Game> games) {
for (Game game : games) {
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java
index 281f346b15..f712752e66 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -35,7 +35,8 @@ public class JdbcPlayerDao implements PlayerDao {
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
- public void savePlayer(Player player) {
+ @Override
+ public void savePlayer(Player player) {
namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player));
}
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java
index beb8bb40e7..f7e19a8c36 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -34,7 +34,8 @@ public class JdbcPlayerSummaryDao implements ItemWriter {
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
- public void write(List extends PlayerSummary> summaries) {
+ @Override
+ public void write(List extends PlayerSummary> summaries) {
for (PlayerSummary summary : summaries) {
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java
index 6b40468b4e..b3203d9193 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -22,6 +22,7 @@
public class PlayerFieldSetMapper implements FieldSetMapper {
+ @Override
public Player mapFieldSet(FieldSet fs) {
if(fs == null){
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java
index 13eda4b09f..088e85382f 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -26,6 +26,7 @@ public class PlayerItemWriter implements ItemWriter {
private PlayerDao playerDao;
+ @Override
public void write(List extends Player> players) throws Exception {
for (Player player : players) {
playerDao.savePlayer(player);
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java
index ae14ccef01..eaade25023 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -19,19 +19,21 @@
import java.sql.SQLException;
import org.springframework.batch.core.test.football.PlayerSummary;
-import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
+import org.springframework.jdbc.core.RowMapper;
/**
- * RowMapper used to map a ResultSet to a {@link PlayerSummary}
+ * RowMapper used to map a ResultSet to a {@link org.springframework.batch.core.test.football.PlayerSummary}
*
* @author Lucas Ward
+ * @author Mahmoud Ben Hassine
*
*/
-public class PlayerSummaryMapper implements ParameterizedRowMapper {
+public class PlayerSummaryMapper implements RowMapper {
/* (non-Javadoc)
* @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int)
*/
+ @Override
public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException {
PlayerSummary summary = new PlayerSummary();
diff --git a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java
index 11cf08b72b..e49cd22645 100644
--- a/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java
+++ b/spring-batch-core-tests/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -22,17 +22,19 @@
import org.springframework.jdbc.core.RowMapper;
/**
- * RowMapper used to map a ResultSet to a {@link PlayerSummary}
+ * RowMapper used to map a ResultSet to a {@link org.springframework.batch.core.test.football.PlayerSummary}
*
* @author Lucas Ward
+ * @author Mahmoud Ben Hassine
*
*/
-public class PlayerSummaryRowMapper implements RowMapper {
+public class PlayerSummaryRowMapper implements RowMapper {
/* (non-Javadoc)
* @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int)
*/
- public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ @Override
+ public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException {
PlayerSummary summary = new PlayerSummary();
diff --git a/spring-batch-core-tests/src/main/resources/META-INF/batch/footballJob.xml b/spring-batch-core-tests/src/main/resources/META-INF/batch/footballJob.xml
index 8d45077b45..ba8e595b32 100644
--- a/spring-batch-core-tests/src/main/resources/META-INF/batch/footballJob.xml
+++ b/spring-batch-core-tests/src/main/resources/META-INF/batch/footballJob.xml
@@ -3,9 +3,9 @@
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/aop%20http://www.springframework.org/schema/aop/spring-aop-3.1.xsd-http://www.springframework.org/schema/batch%20http://www.springframework.org/schema/batch/spring-batch-2.2.xsd-http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+ xsi:schemaLocation="http://www.springframework.org/schema/aop%20https://www.springframework.org/schema/aop/spring-aop-3.1.xsd+http://www.springframework.org/schema/batch%20https://www.springframework.org/schema/batch/spring-batch-2.2.xsd+http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
diff --git a/spring-batch-core-tests/src/main/resources/META-INF/batch/footballSkipJob.xml b/spring-batch-core-tests/src/main/resources/META-INF/batch/footballSkipJob.xml
index e6e0f7c737..97942bc196 100644
--- a/spring-batch-core-tests/src/main/resources/META-INF/batch/footballSkipJob.xml
+++ b/spring-batch-core-tests/src/main/resources/META-INF/batch/footballSkipJob.xml
@@ -1,9 +1,9 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/aop%20https://www.springframework.org/schema/aop/spring-aop-3.1.xsd+http://www.springframework.org/schema/batch%20https://www.springframework.org/schema/batch/spring-batch-2.2.xsd+http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
diff --git a/spring-batch-core-tests/src/main/resources/META-INF/batch/parallelJob.xml b/spring-batch-core-tests/src/main/resources/META-INF/batch/parallelJob.xml
index 76de2415fe..37570802d7 100644
--- a/spring-batch-core-tests/src/main/resources/META-INF/batch/parallelJob.xml
+++ b/spring-batch-core-tests/src/main/resources/META-INF/batch/parallelJob.xml
@@ -3,9 +3,9 @@
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/aop%20http://www.springframework.org/schema/aop/spring-aop-3.1.xsd-http://www.springframework.org/schema/batch%20http://www.springframework.org/schema/batch/spring-batch-2.2.xsd-http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+ xsi:schemaLocation="http://www.springframework.org/schema/aop%20https://www.springframework.org/schema/aop/spring-aop-3.1.xsd+http://www.springframework.org/schema/batch%20https://www.springframework.org/schema/batch/spring-batch-2.2.xsd+http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
diff --git a/spring-batch-core-tests/src/main/resources/META-INF/batch/timeoutJob.xml b/spring-batch-core-tests/src/main/resources/META-INF/batch/timeoutJob.xml
new file mode 100644
index 0000000000..01786d89ce
--- /dev/null
+++ b/spring-batch-core-tests/src/main/resources/META-INF/batch/timeoutJob.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-batch-core-tests/src/main/resources/log4j.properties b/spring-batch-core-tests/src/main/resources/log4j.properties
index f8c8855ebc..ab37ea0326 100644
--- a/spring-batch-core-tests/src/main/resources/log4j.properties
+++ b/spring-batch-core-tests/src/main/resources/log4j.properties
@@ -1,7 +1,7 @@
log4j.rootCategory=INFO, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout=org.apache.logging.log4j.core.appender.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.logging.log4j.core.layout.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%L - %m%n
log4j.category.org.apache.activemq=ERROR
diff --git a/spring-batch-core-tests/src/site/apt/index.apt b/spring-batch-core-tests/src/site/apt/index.apt
deleted file mode 100644
index 45d636ad3c..0000000000
--- a/spring-batch-core-tests/src/site/apt/index.apt
+++ /dev/null
@@ -1,15 +0,0 @@
- ------
- Spring Batch Integration Tests
- ------
- Dave Syer
- ------
- March 2008
-
-Overview of the Spring Batch Integration Tests
-
- This module contains integration tests for the Spring Batch Infrastructure module. In the tests we exercise some extended and mostly realistic scenarios using the infrastructure components.
-
- * Message-pipeline tests. There are a bunch of tests using JMS and RDBMS in the same transaction, exercising various failure and retry scenarios. The basic premise is that throughput in such systems is greatly increased by widening the transactio nboundaries to process more than one message in each transaction. If there is a failure we may want to retry the operation in the next transaction.
-
- * OXM integration tests. There are also some tests of the XML reader and writers in Spring Batch with more extensive configuration than in the unit tests.
-
diff --git a/spring-batch-core-tests/src/site/site.xml b/spring-batch-core-tests/src/site/site.xml
deleted file mode 100644
index 29c2887830..0000000000
--- a/spring-batch-core-tests/src/site/site.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/AbstractIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/AbstractIntegrationTests.java
new file mode 100644
index 0000000000..e136803682
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/AbstractIntegrationTests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2006-2019 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
+ *
+ * https://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.core.test;
+
+import javax.sql.DataSource;
+
+import org.junit.Before;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+
+/**
+ * @author Mahmoud Ben Hassine
+ */
+public class AbstractIntegrationTests {
+
+ protected DataSource dataSource;
+
+ @Before
+ public void setUp() {
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-drop-hsqldb.sql"));
+ databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-hsqldb.sql"));
+ databasePopulator.addScript(new ClassPathResource("/business-schema-hsqldb.sql"));
+ databasePopulator.execute(this.dataSource);
+ }
+
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/IgnoredTestSuite.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/IgnoredTestSuite.java
index 513b54d9f5..48730ec659 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/IgnoredTestSuite.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/IgnoredTestSuite.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java
new file mode 100644
index 0000000000..e7c0898553
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2015-2019 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
+ *
+ * https://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.core.test.concurrent;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLException;
+import java.sql.Statement;
+import javax.sql.DataSource;
+
+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.JobParameters;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepContribution;
+import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.core.job.builder.FlowBuilder;
+import org.springframework.batch.core.job.flow.Flow;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
+import org.springframework.batch.core.scope.context.ChunkContext;
+import org.springframework.batch.core.step.tasklet.Tasklet;
+import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.lang.Nullable;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.ClassUtils;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Michael Minella
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = ConcurrentTransactionTests.ConcurrentJobConfiguration.class)
+public class ConcurrentTransactionTests {
+
+ @Autowired
+ private Job concurrentJob;
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @DirtiesContext
+ @Test
+ public void testConcurrentLongRunningJobExecutions() throws Exception {
+
+ JobExecution jobExecution = jobLauncher.run(concurrentJob, new JobParameters());
+
+ assertEquals(jobExecution.getStatus(), BatchStatus.COMPLETED);
+ }
+
+ @Configuration
+ @EnableBatchProcessing
+ public static class ConcurrentJobConfiguration extends DefaultBatchConfigurer {
+
+ @Autowired
+ private JobBuilderFactory jobBuilderFactory;
+
+ @Autowired
+ private StepBuilderFactory stepBuilderFactory;
+
+ @Bean
+ public TaskExecutor taskExecutor() {
+ return new SimpleAsyncTaskExecutor();
+ }
+
+ /**
+ * This datasource configuration configures the HSQLDB instance using MVCC. When
+ * configured using the default behavior, transaction serialization errors are
+ * thrown (default configuration example below).
+ *
+ * return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder().
+ * addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql").
+ * addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").
+ * build());
+
+ * @return
+ */
+ @Bean
+ DataSource dataSource() {
+ ResourceLoader defaultResourceLoader = new DefaultResourceLoader();
+ EmbeddedDatabaseFactory embeddedDatabaseFactory = new EmbeddedDatabaseFactory();
+ embeddedDatabaseFactory.setDatabaseConfigurer(new EmbeddedDatabaseConfigurer() {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
+ try {
+ properties.setDriverClass((Class extends Driver>) ClassUtils.forName("org.hsqldb.jdbcDriver", this.getClass().getClassLoader()));
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ properties.setUrl("jdbc:hsqldb:mem:" + databaseName + ";hsqldb.tx=mvcc");
+ properties.setUsername("sa");
+ properties.setPassword("");
+ }
+
+ @Override
+ public void shutdown(DataSource dataSource, String databaseName) {
+ try {
+ Connection connection = dataSource.getConnection();
+ Statement stmt = connection.createStatement();
+ stmt.execute("SHUTDOWN");
+ }
+ catch (SQLException ex) {
+ }
+ }
+ });
+
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.addScript(defaultResourceLoader.getResource("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"));
+ databasePopulator.addScript(defaultResourceLoader.getResource("classpath:org/springframework/batch/core/schema-hsqldb.sql"));
+ embeddedDatabaseFactory.setDatabasePopulator(databasePopulator);
+
+ return embeddedDatabaseFactory.getDatabase();
+ }
+
+ @Bean
+ public Flow flow() {
+ return new FlowBuilder("flow")
+ .start(stepBuilderFactory.get("flow.step1")
+ .tasklet(new Tasklet() {
+ @Nullable
+ @Override
+ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
+ return RepeatStatus.FINISHED;
+ }
+ }).build()
+ ).next(stepBuilderFactory.get("flow.step2")
+ .tasklet(new Tasklet() {
+ @Nullable
+ @Override
+ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
+ return RepeatStatus.FINISHED;
+ }
+ }).build()
+ ).build();
+ }
+
+ @Bean
+ public Step firstStep() {
+ return stepBuilderFactory.get("firstStep")
+ .tasklet(new Tasklet() {
+ @Nullable
+ @Override
+ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
+ System.out.println(">> Beginning concurrent job test");
+ return RepeatStatus.FINISHED;
+ }
+ }).build();
+ }
+
+ @Bean
+ public Step lastStep() {
+ return stepBuilderFactory.get("lastStep")
+ .tasklet(new Tasklet() {
+ @Nullable
+ @Override
+ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
+ System.out.println(">> Ending concurrent job test");
+ return RepeatStatus.FINISHED;
+ }
+ }).build();
+ }
+
+ @Bean
+ public Job concurrentJob() {
+ Flow splitFlow = new FlowBuilder("splitflow").split(new SimpleAsyncTaskExecutor()).add(flow(), flow(), flow(), flow(), flow(), flow(), flow()).build();
+
+ return jobBuilderFactory.get("concurrentJob")
+ .start(firstStep())
+ .next(stepBuilderFactory.get("splitFlowStep")
+ .flow(splitFlow)
+ .build())
+ .next(lastStep())
+ .build();
+ }
+
+ @Override
+ protected JobRepository createJobRepository() throws Exception {
+ JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
+ factory.setDataSource(dataSource());
+ factory.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
+ factory.setTransactionManager(getTransactionManager());
+ factory.afterPropertiesSet();
+ return factory.getObject();
+ }
+ }
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java
index 240fa23424..d3d56d1e80 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java
@@ -1,84 +1,76 @@
-/*
- * Copyright 2006-2009 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.core.test.football;
-
-import static org.junit.Assert.assertEquals;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Before;
-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.JobParametersBuilder;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.core.launch.JobLauncher;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.jdbc.JdbcTestUtils;
-
-/**
- * @author Dave Syer
- *
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballJob.xml" })
-public class FootballJobIntegrationTests {
-
- /** Logger */
- private final Log logger = LogFactory.getLog(getClass());
-
- private JdbcTemplate jdbcTemplate;
-
- @Autowired
- private JobLauncher jobLauncher;
-
- @Autowired
- private Job job;
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- this.jdbcTemplate = new JdbcTemplate(dataSource);
- }
-
- @Before
- public void clear() {
- JdbcTestUtils.deleteFromTables(jdbcTemplate, "PLAYER_SUMMARY", "GAMES", "PLAYERS");
- }
-
- @Test
- public void testLaunchJob() throws Exception {
- JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("commit.interval", 10L)
- .toJobParameters());
- assertEquals(BatchStatus.COMPLETED, execution.getStatus());
- for (StepExecution stepExecution : execution.getStepExecutions()) {
- logger.info("Processed: " + stepExecution);
- if (stepExecution.getStepName().equals("playerload")) {
- // The effect of the retries
- assertEquals(new Double(Math.ceil(stepExecution.getReadCount() / 10. + 1)).intValue(),
- stepExecution.getCommitCount());
- }
- }
- }
-
-}
+/*
+ * Copyright 2006-2019 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
+ *
+ * https://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.core.test.football;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.JobParametersBuilder;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.test.AbstractIntegrationTests;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Dave Syer
+ * @author Mahmoud Ben Hassine
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballJob.xml" })
+public class FootballJobIntegrationTests extends AbstractIntegrationTests {
+
+ /** Logger */
+ private final Log logger = LogFactory.getLog(getClass());
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ private Job job;
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Test
+ public void testLaunchJob() throws Exception {
+ JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("commit.interval", 10L)
+ .toJobParameters());
+ assertEquals(BatchStatus.COMPLETED, execution.getStatus());
+ for (StepExecution stepExecution : execution.getStepExecutions()) {
+ logger.info("Processed: " + stepExecution);
+ if (stepExecution.getStepName().equals("playerload")) {
+ // The effect of the retries
+ assertEquals(new Double(Math.ceil(stepExecution.getReadCount() / 10. + 1)).intValue(),
+ stepExecution.getCommitCount());
+ }
+ }
+ }
+
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java
index feceecc206..2565dddd46 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java
@@ -1,116 +1,112 @@
-/*
- * Copyright 2006-2009 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.core.test.football;
-
-import static org.junit.Assert.assertEquals;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Before;
-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.JobParametersBuilder;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.core.launch.JobLauncher;
-import org.springframework.batch.support.DatabaseType;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.jdbc.JdbcTestUtils;
-
-/**
- * @author Dave Syer
- *
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballSkipJob.xml" })
-public class FootballJobSkipIntegrationTests {
-
- /** Logger */
- private final Log logger = LogFactory.getLog(getClass());
-
- private JdbcTemplate jdbcTemplate;
-
- @Autowired
- private JobLauncher jobLauncher;
-
- @Autowired
- private Job job;
-
- private DatabaseType databaseType;
-
- @Autowired
- public void setDataSource(DataSource dataSource) throws Exception {
- this.jdbcTemplate = new JdbcTemplate(dataSource);
- databaseType = DatabaseType.fromMetaData(dataSource);
- }
-
- @Before
- public void clear() {
- JdbcTestUtils.deleteFromTables(jdbcTemplate, "PLAYER_SUMMARY", "GAMES", "PLAYERS");
- }
-
- @Test
- public void testLaunchJob() throws Exception {
- try {
- if (databaseType == DatabaseType.POSTGRES || databaseType == DatabaseType.ORACLE) {
- // Extra special test for these platforms (would have failed
- // the job with UNKNOWN status in Batch 2.0):
- jdbcTemplate.update("SET CONSTRAINTS ALL DEFERRED");
- }
- }
- catch (Exception e) {
- // Ignore (wrong platform)
- }
- JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("skip.limit", 0L)
- .toJobParameters());
- assertEquals(BatchStatus.COMPLETED, execution.getStatus());
- for (StepExecution stepExecution : execution.getStepExecutions()) {
- logger.info("Processed: " + stepExecution);
- }
- // They all skip on the second execution because of a primary key
- // violation
- long retryLimit = 2L;
- execution = jobLauncher.run(job,
- new JobParametersBuilder().addLong("skip.limit", 100000L).addLong("retry.limit", retryLimit)
- .toJobParameters());
- assertEquals(BatchStatus.COMPLETED, execution.getStatus());
- for (StepExecution stepExecution : execution.getStepExecutions()) {
- logger.info("Processed: " + stepExecution);
- if (stepExecution.getStepName().equals("playerload")) {
- // The effect of the retries is to increase the number of
- // rollbacks
- int commitInterval = stepExecution.getReadCount() / (stepExecution.getCommitCount() - 1);
- // Account for the extra empty commit if the read count is
- // commensurate with the commit interval
- int effectiveCommitCount = stepExecution.getReadCount() % commitInterval == 0 ? stepExecution
- .getCommitCount() - 1 : stepExecution.getCommitCount();
- long expectedRollbacks = Math.max(1, retryLimit) * effectiveCommitCount + stepExecution.getReadCount();
- assertEquals(expectedRollbacks, stepExecution.getRollbackCount());
- assertEquals(stepExecution.getReadCount(), stepExecution.getWriteSkipCount());
- }
- }
-
- }
-
-}
+/*
+ * Copyright 2006-2019 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
+ *
+ * https://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.core.test.football;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.JobParametersBuilder;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.test.AbstractIntegrationTests;
+import org.springframework.batch.support.DatabaseType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Dave Syer
+ * @author Mahmoud Ben Hassine
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballSkipJob.xml" })
+public class FootballJobSkipIntegrationTests extends AbstractIntegrationTests {
+
+ /** Logger */
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ private Job job;
+
+ private DatabaseType databaseType;
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) throws Exception {
+ this.dataSource = dataSource;
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ databaseType = DatabaseType.fromMetaData(dataSource);
+ }
+
+ @Test
+ public void testLaunchJob() throws Exception {
+ try {
+ if (databaseType == DatabaseType.POSTGRES || databaseType == DatabaseType.ORACLE) {
+ // Extra special test for these platforms (would have failed
+ // the job with UNKNOWN status in Batch 2.0):
+ jdbcTemplate.update("SET CONSTRAINTS ALL DEFERRED");
+ }
+ }
+ catch (Exception e) {
+ // Ignore (wrong platform)
+ }
+ JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("skip.limit", 0L)
+ .toJobParameters());
+ assertEquals(BatchStatus.COMPLETED, execution.getStatus());
+ for (StepExecution stepExecution : execution.getStepExecutions()) {
+ logger.info("Processed: " + stepExecution);
+ }
+ // They all skip on the second execution because of a primary key
+ // violation
+ long retryLimit = 2L;
+ execution = jobLauncher.run(job,
+ new JobParametersBuilder().addLong("skip.limit", 100000L).addLong("retry.limit", retryLimit)
+ .toJobParameters());
+ assertEquals(BatchStatus.COMPLETED, execution.getStatus());
+ for (StepExecution stepExecution : execution.getStepExecutions()) {
+ logger.info("Processed: " + stepExecution);
+ if (stepExecution.getStepName().equals("playerload")) {
+ // The effect of the retries is to increase the number of
+ // rollbacks
+ int commitInterval = stepExecution.getReadCount() / (stepExecution.getCommitCount() - 1);
+ // Account for the extra empty commit if the read count is
+ // commensurate with the commit interval
+ int effectiveCommitCount = stepExecution.getReadCount() % commitInterval == 0 ? stepExecution
+ .getCommitCount() - 1 : stepExecution.getCommitCount();
+ long expectedRollbacks = Math.max(1, retryLimit) * effectiveCommitCount + stepExecution.getReadCount();
+ assertEquals(expectedRollbacks, stepExecution.getRollbackCount());
+ assertEquals(stepExecution.getReadCount(), stepExecution.getWriteSkipCount());
+ }
+ }
+
+ }
+
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java
index 61c590d4f4..fd85cf08b5 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java
new file mode 100644
index 0000000000..148c593207
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2005-2014 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
+ *
+ * https://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.core.test.ldif;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.net.MalformedURLException;
+
+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.launch.JobLauncher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.Assert;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/applicationContext-test1.xml"})
+public class LdifReaderTests {
+
+ private Resource expected;
+ private Resource actual;
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ @Qualifier("job1")
+ private Job job1;
+
+ @Autowired
+ @Qualifier("job2")
+ private Job job2;
+
+ public LdifReaderTests() throws MalformedURLException {
+ expected = new ClassPathResource("/expectedOutput.ldif");
+ actual = new UrlResource("file:target/test-outputs/output.ldif");
+ }
+
+ @Before
+ public void checkFiles() {
+ Assert.isTrue(expected.exists(), "Expected does not exist.");
+ }
+
+ @Test
+ public void testValidRun() throws Exception {
+ JobExecution jobExecution = jobLauncher.run(job1, new JobParameters());
+
+ //Ensure job completed successfully.
+ Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
+
+ //Check output.
+ Assert.isTrue(actual.exists(), "Actual does not exist.");
+ compareFiles(expected.getFile(), actual.getFile());
+ }
+
+ @Test
+ public void testResourceNotExists() throws Exception {
+ JobExecution jobExecution = jobLauncher.run(job2, new JobParameters());
+
+ Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
+ Assert.isTrue(jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
+ }
+
+ private void compareFiles(File expected, File actual) throws Exception {
+ BufferedReader expectedReader = new BufferedReader(new FileReader(expected));
+ BufferedReader actualReader = new BufferedReader(new FileReader(actual));
+ try {
+ int lineNum = 1;
+ for (String expectedLine = null; (expectedLine = expectedReader.readLine()) != null; lineNum++) {
+ String actualLine = actualReader.readLine();
+ assertEquals("Line number " + lineNum + " does not match.", expectedLine, actualLine);
+ }
+
+ String actualLine = actualReader.readLine();
+ assertEquals("More lines than expected. There should not be a line number " + lineNum + ".", null, actualLine);
+ }
+ finally {
+ expectedReader.close();
+ actualReader.close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java
new file mode 100644
index 0000000000..a0f7f41e24
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2005-2014 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
+ *
+ * https://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.core.test.ldif;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.launch.JobLauncher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.Assert;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/applicationContext-test2.xml"})
+public class MappingLdifReaderTests {
+ private static Logger log = LoggerFactory.getLogger(MappingLdifReaderTests.class);
+
+ private Resource expected;
+ private Resource actual;
+
+ @Autowired
+ private JobLauncher launcher;
+
+ @Autowired
+ @Qualifier("job1")
+ private Job job1;
+
+ @Autowired
+ @Qualifier("job2")
+ private Job job2;
+
+ public MappingLdifReaderTests() throws MalformedURLException {
+ expected = new ClassPathResource("/expectedOutput.ldif");
+ actual = new UrlResource("file:target/test-outputs/output.ldif");
+ }
+
+ @Before
+ public void checkFiles() {
+ Assert.isTrue(expected.exists(), "Expected does not exist.");
+ }
+
+ @Test
+ public void testValidRun() throws Exception {
+ JobExecution jobExecution = launcher.run(job1, new JobParameters());
+
+ //Ensure job completed successfully.
+ Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
+
+ //Check output.
+ Assert.isTrue(actual.exists(), "Actual does not exist.");
+ Assert.isTrue(compareFiles(expected.getFile(), actual.getFile()), "Files were not equal");
+ }
+
+ @Test
+ public void testResourceNotExists() throws Exception {
+ JobExecution jobExecution = launcher.run(job2, new JobParameters());
+
+ Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
+ Assert.isTrue(jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
+ }
+
+
+ private boolean compareFiles(File expected, File actual) throws Exception {
+ boolean equal = true;
+
+ FileInputStream expectedStream = new FileInputStream(expected);
+ FileInputStream actualStream = new FileInputStream(actual);
+
+ //Construct BufferedReader from InputStreamReader
+ BufferedReader expectedReader = new BufferedReader(new InputStreamReader(expectedStream));
+ BufferedReader actualReader = new BufferedReader(new InputStreamReader(actualStream));
+
+ String line = null;
+ while ((line = expectedReader.readLine()) != null) {
+ if(!line.equals(actualReader.readLine())) {
+ equal = false;
+ break;
+ }
+ }
+
+ if(actualReader.readLine() != null) {
+ equal = false;
+ }
+
+ expectedReader.close();
+
+ return equal;
+ }
+}
\ No newline at end of file
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java
new file mode 100644
index 0000000000..cbbb2a9cc4
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2005-2019 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
+ *
+ * https://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.core.test.ldif;
+
+import org.springframework.batch.item.ldif.RecordMapper;
+import org.springframework.lang.Nullable;
+import org.springframework.ldap.core.LdapAttributes;
+
+/**
+ * This default implementation simply returns the LdapAttributes object and is only intended for test. As its not required
+ * to return an object of a specific type to make the MappingLdifReader implementation work, this basic setting is sufficient
+ * to demonstrate its function.
+ *
+ * @author Keith Barlow
+ *
+ */
+public class MyMapper implements RecordMapper {
+
+ @Nullable
+ public LdapAttributes mapRecord(LdapAttributes attributes) {
+ return attributes;
+ }
+
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java
new file mode 100644
index 0000000000..5f9abe1b84
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2017 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
+ *
+ * https://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.core.test.ldif.builder;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.batch.item.ItemStreamException;
+import org.springframework.batch.item.ldif.LdifReader;
+import org.springframework.batch.item.ldif.RecordCallbackHandler;
+import org.springframework.batch.item.ldif.builder.LdifReaderBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.ldap.core.LdapAttributes;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Glenn Renfro
+ */
+@RunWith(SpringRunner.class)
+public class LdifReaderBuilderTests {
+
+ @Autowired
+ private ApplicationContext context;
+
+ private LdifReader ldifReader;
+
+ private String callbackAttributeName;
+
+ @After
+ public void tearDown() {
+ this.callbackAttributeName = null;
+ if (this.ldifReader != null) {
+ this.ldifReader.close();
+ }
+ }
+
+ @Test
+ public void testSkipRecord() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().recordsToSkip(1).resource(context.getResource("classpath:/test.ldif"))
+ .name("foo").build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the second record did not match expected result",
+ "cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testBasicRead() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo").build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the first record did not match expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testCurrentItemCount() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().currentItemCount(3)
+ .resource(context.getResource("classpath:/test.ldif")).name("foo").build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the third record did not match expected result",
+ "cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testMaxItemCount() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().maxItemCount(1).resource(context.getResource("classpath:/test.ldif"))
+ .name("foo").build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the first record did not match expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString());
+ ldapAttributes = this.ldifReader.read();
+ assertNull("The second read should have returned null", ldapAttributes);
+ }
+
+ @Test
+ public void testSkipRecordCallback() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().recordsToSkip(1).skippedRecordsCallback(new TestCallBackHandler())
+ .resource(context.getResource("classpath:/test.ldif")).name("foo").build();
+ firstRead();
+ assertEquals("The attribute name from the callback handler did not match the expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", this.callbackAttributeName);
+ }
+
+ @Test
+ public void testSaveState() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo").build();
+ ExecutionContext executionContext = new ExecutionContext();
+ firstRead(executionContext);
+ this.ldifReader.update(executionContext);
+ assertEquals("foo.read.count did not have the expected result", 1,
+ executionContext.getInt("foo.read.count"));
+ }
+
+ @Test
+ public void testSaveStateDisabled() throws Exception {
+ this.ldifReader = new LdifReaderBuilder().saveState(false).resource(context.getResource("classpath:/test.ldif"))
+ .build();
+ ExecutionContext executionContext = new ExecutionContext();
+ firstRead(executionContext);
+ this.ldifReader.update(executionContext);
+ assertEquals("ExecutionContext should have been empty", 0, executionContext.size());
+ }
+
+ @Test
+ public void testStrict() {
+ // Test that strict when enabled will throw an exception.
+ try {
+ this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/teadsfst.ldif")).name("foo").build();
+ this.ldifReader.open(new ExecutionContext());
+ fail("IllegalStateException should have been thrown, because strict was set to true");
+ }
+ catch (ItemStreamException ise) {
+ assertEquals("IllegalStateException message did not match the expected result.",
+ "Failed to initialize the reader", ise.getMessage());
+ }
+ // Test that strict when disabled will still allow the ldap resource to be opened.
+ this.ldifReader = new LdifReaderBuilder().strict(false)
+ .resource(context.getResource("classpath:/teadsfst.ldif")).name("foo").build();
+ this.ldifReader.open(new ExecutionContext());
+ }
+
+ private LdapAttributes firstRead() throws Exception {
+ return firstRead(new ExecutionContext());
+ }
+
+ private LdapAttributes firstRead(ExecutionContext executionContext) throws Exception {
+ this.ldifReader.open(executionContext);
+ return this.ldifReader.read();
+ }
+
+ @Configuration
+ public static class LdifConfiguration {
+
+ }
+
+ public class TestCallBackHandler implements RecordCallbackHandler {
+
+ @Override
+ public void handleRecord(LdapAttributes attributes) {
+ callbackAttributeName = attributes.getName().toString();
+ }
+ }
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java
new file mode 100644
index 0000000000..aef6c5bb19
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2017-2019 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
+ *
+ * https://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.core.test.ldif.builder;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.batch.item.ItemStreamException;
+import org.springframework.batch.item.ldif.MappingLdifReader;
+import org.springframework.batch.item.ldif.RecordCallbackHandler;
+import org.springframework.batch.item.ldif.RecordMapper;
+import org.springframework.batch.item.ldif.builder.MappingLdifReaderBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.lang.Nullable;
+import org.springframework.ldap.core.LdapAttributes;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Glenn Renfro
+ */
+@RunWith(SpringRunner.class)
+public class MappingLdifReaderBuilderTests {
+ @Autowired
+ private ApplicationContext context;
+
+ private MappingLdifReader mappingLdifReader;
+
+ private String callbackAttributeName;
+
+ @After
+ public void tearDown() {
+ this.callbackAttributeName = null;
+ if (this.mappingLdifReader != null) {
+ this.mappingLdifReader.close();
+ }
+ }
+
+ @Test
+ public void testSkipRecord() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .recordsToSkip(1)
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the second record did not match expected result",
+ "cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testBasicRead() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the first record did not match expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testCurrentItemCount() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .currentItemCount(3)
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the third record did not match expected result",
+ "cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com", ldapAttributes.getName().toString());
+ }
+
+ @Test
+ public void testMaxItemCount() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .maxItemCount(1)
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ LdapAttributes ldapAttributes = firstRead();
+ assertEquals("The attribute name for the first record did not match expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString());
+ ldapAttributes = this.mappingLdifReader.read();
+ assertNull("The second read should have returned null", ldapAttributes);
+ }
+
+ @Test
+ public void testSkipRecordCallback() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .recordsToSkip(1)
+ .recordMapper(new TestMapper())
+ .skippedRecordsCallback(new TestCallBackHandler())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ firstRead();
+ assertEquals("The attribute name from the callback handler did not match the expected result",
+ "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", this.callbackAttributeName);
+ }
+
+ @Test
+ public void testSaveState() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .name("foo")
+ .build();
+ ExecutionContext executionContext = new ExecutionContext();
+ firstRead(executionContext);
+ this.mappingLdifReader.update(executionContext);
+ assertEquals("foo.read.count did not have the expected result", 1,
+ executionContext.getInt("foo.read.count"));
+ }
+
+ @Test
+ public void testSaveStateDisabled() throws Exception {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .saveState(false)
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/test.ldif"))
+ .build();
+ ExecutionContext executionContext = new ExecutionContext();
+ firstRead(executionContext);
+ this.mappingLdifReader.update(executionContext);
+ assertEquals("ExecutionContext should have been empty", 0, executionContext.size());
+ }
+
+ @Test
+ public void testStrict() {
+ // Test that strict when enabled will throw an exception.
+ try {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .recordMapper(new TestMapper())
+ .resource(context.getResource("classpath:/teadsfst.ldif"))
+ .name("foo")
+ .build();
+ this.mappingLdifReader.open(new ExecutionContext());
+ fail("IllegalStateException should have been thrown, because strict was set to true");
+ }
+ catch (ItemStreamException ise) {
+ assertEquals("IllegalStateException message did not match the expected result.",
+ "Failed to initialize the reader", ise.getMessage());
+ }
+ // Test that strict when disabled will still allow the ldap resource to be opened.
+ this.mappingLdifReader = new MappingLdifReaderBuilder().strict(false).name("foo")
+ .recordMapper(new TestMapper()).resource(context.getResource("classpath:/teadsfst.ldif")).build();
+ this.mappingLdifReader.open(new ExecutionContext());
+ }
+
+ @Test
+ public void testNullRecordMapper() {
+ try {
+ this.mappingLdifReader = new MappingLdifReaderBuilder()
+ .resource(context.getResource("classpath:/teadsfst.ldif"))
+ .build();
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException ise) {
+ assertEquals("IllegalArgumentException message did not match the expected result.",
+ "RecordMapper is required.", ise.getMessage());
+ }
+
+ }
+
+ private LdapAttributes firstRead() throws Exception {
+ return firstRead(new ExecutionContext());
+ }
+
+ private LdapAttributes firstRead(ExecutionContext executionContext) throws Exception {
+ this.mappingLdifReader.open(executionContext);
+ return this.mappingLdifReader.read();
+ }
+
+ @Configuration
+ public static class LdifConfiguration {
+
+ }
+
+ public class TestCallBackHandler implements RecordCallbackHandler {
+
+ @Override
+ public void handleRecord(LdapAttributes attributes) {
+ callbackAttributeName = attributes.getName().toString();
+ }
+ }
+
+ public class TestMapper implements RecordMapper {
+ @Nullable
+ @Override
+ public LdapAttributes mapRecord(LdapAttributes attributes) {
+ return attributes;
+ }
+ }
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/ConcurrentMapExecutionContextDaoTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/ConcurrentMapExecutionContextDaoTests.java
index 1fe63dd590..71e741f805 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/ConcurrentMapExecutionContextDaoTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/ConcurrentMapExecutionContextDaoTests.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -60,8 +60,9 @@ public void testSaveUpdate() throws Exception {
public void testTransactionalSaveUpdate() throws Exception {
final StepExecution stepExecution = new StepExecution("step", new JobExecution(11L));
stepExecution.setId(123L);
- new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
+ new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
+ @Override
+ public Void doInTransaction(TransactionStatus status) {
stepExecution.getExecutionContext().put("foo", "bar");
dao.saveExecutionContext(stepExecution);
return null;
@@ -76,7 +77,7 @@ public Object doInTransaction(TransactionStatus status) {
public void testConcurrentTransactionalSaveUpdate() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(3);
- CompletionService completionService = new ExecutorCompletionService(executor);
+ CompletionService completionService = new ExecutorCompletionService<>(executor);
final int outerMax = 10;
final int innerMax = 100;
@@ -89,6 +90,7 @@ public void testConcurrentTransactionalSaveUpdate() throws Exception {
stepExecution2.setId(1234L + i);
completionService.submit(new Callable() {
+ @Override
public StepExecution call() throws Exception {
for (int i = 0; i < innerMax; i++) {
String value = "bar" + i;
@@ -99,6 +101,7 @@ public StepExecution call() throws Exception {
});
completionService.submit(new Callable() {
+ @Override
public StepExecution call() throws Exception {
for (int i = 0; i < innerMax; i++) {
String value = "spam" + i;
@@ -119,8 +122,9 @@ public StepExecution call() throws Exception {
private void saveAndAssert(final StepExecution stepExecution, final String value) {
- new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
+ new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
+ @Override
+ public Void doInTransaction(TransactionStatus status) {
stepExecution.getExecutionContext().put("foo", value);
dao.saveExecutionContext(stepExecution);
return null;
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java
index 8614b2e4f3..ac0b268e91 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -15,47 +15,48 @@
*/
package org.springframework.batch.core.test.repository;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.test.AbstractIntegrationTests;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml" })
-public class JdbcJobRepositoryTests {
+public class JdbcJobRepositoryTests extends AbstractIntegrationTests {
private JobSupport job;
- private Set jobExecutionIds = new HashSet();
+ private Set jobExecutionIds = new HashSet<>();
- private Set jobIds = new HashSet();
+ private Set jobIds = new HashSet<>();
- private List list = new ArrayList();
+ private List list = new ArrayList<>();
private JdbcTemplate jdbcTemplate;
@@ -67,35 +68,15 @@ public class JdbcJobRepositoryTests {
@Autowired
public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Before
public void onSetUpInTransaction() throws Exception {
+ super.setUp();
job = new JobSupport("test-job");
job.setRestartable(true);
- jdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION_CONTEXT");
- jdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_CONTEXT");
- jdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION");
- jdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_PARAMS");
- jdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION");
- jdbcTemplate.update("DELETE FROM BATCH_JOB_INSTANCE");
- }
-
- @After
- public void onTearDownAfterTransaction() throws Exception {
- for (Long id : jobExecutionIds) {
- jdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_CONTEXT where JOB_EXECUTION_ID=?", id);
- jdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=?", id);
- }
- for (Long id : jobIds) {
- jdbcTemplate.update("DELETE FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", id);
- }
- for (Long id : jobIds) {
- int count = jdbcTemplate.queryForInt(
- "SELECT COUNT(*) FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", id);
- assertEquals(0, count);
- }
}
@Test
@@ -103,7 +84,7 @@ public void testFindOrCreateJob() throws Exception {
job.setName("foo");
int before = 0;
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
- int after = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
+ int after = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE", Integer.class);
assertEquals(before + 1, after);
assertNotNull(execution.getId());
}
@@ -115,7 +96,7 @@ public void testFindOrCreateJobWithExecutionContext() throws Exception {
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
execution.getExecutionContext().put("foo", "bar");
repository.updateExecutionContext(execution);
- int after = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_EXECUTION_CONTEXT");
+ int after = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM BATCH_JOB_EXECUTION_CONTEXT", Integer.class);
assertEquals(before + 1, after);
assertNotNull(execution.getId());
JobExecution last = repository.getLastJobExecution(job.getName(), new JobParameters());
@@ -145,7 +126,7 @@ public void testFindOrCreateJobConcurrently() throws Exception {
assertNotNull(execution);
- int after = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
+ int after = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE", Integer.class);
assertNotNull(execution.getId());
assertEquals(before + 1, after);
@@ -166,7 +147,7 @@ public void testFindOrCreateJobConcurrentlyWhenJobAlreadyExists() throws Excepti
repository.update(execution);
execution.setStatus(BatchStatus.FAILED);
- int before = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
+ int before = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE", Integer.class);
assertEquals(1, before);
long t0 = System.currentTimeMillis();
@@ -179,7 +160,7 @@ public void testFindOrCreateJobConcurrentlyWhenJobAlreadyExists() throws Excepti
}
long t1 = System.currentTimeMillis();
- int after = jdbcTemplate.queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE");
+ int after = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE", Integer.class);
assertNotNull(execution.getId());
assertEquals(before, after);
@@ -197,10 +178,16 @@ private void cacheJobIds(JobExecution execution) {
private JobExecution doConcurrentStart() throws Exception {
new Thread(new Runnable() {
+ @Override
public void run() {
try {
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
+
+ //simulate running execution
+ execution.setStartTime(new Date());
+ repository.update(execution);
+
cacheJobIds(execution);
list.add(execution);
Thread.sleep(1000);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java
index 9183ce255e..b8c3284a0b 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -27,6 +27,7 @@
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.job.DefaultJobParametersValidator;
import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -40,7 +41,7 @@
*/
public class JobSupport implements BeanNameAware, Job {
- private List steps = new ArrayList();
+ private List steps = new ArrayList<>();
private String name;
@@ -77,6 +78,7 @@ public JobSupport(String name) {
*
* @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
*/
+ @Override
public void setBeanName(String name) {
if (this.name == null) {
this.name = name;
@@ -97,6 +99,7 @@ public void setName(String name) {
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.IJob#getName()
*/
+ @Override
public String getName() {
return name;
}
@@ -139,6 +142,7 @@ public void setRestartable(boolean restartable) {
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.IJob#isRestartable()
*/
+ @Override
public boolean isRestartable() {
return restartable;
}
@@ -146,10 +150,13 @@ public boolean isRestartable() {
/* (non-Javadoc)
* @see org.springframework.batch.core.Job#getJobParametersIncrementer()
*/
+ @Nullable
+ @Override
public JobParametersIncrementer getJobParametersIncrementer() {
return null;
}
+ @Override
public JobParametersValidator getJobParametersValidator() {
return jobParametersValidator;
}
@@ -157,10 +164,12 @@ public JobParametersValidator getJobParametersValidator() {
/* (non-Javadoc)
* @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution)
*/
+ @Override
public void execute(JobExecution execution) throws UnexpectedJobExecutionException {
throw new UnsupportedOperationException("JobSupport does not provide an implementation of run(). Use a smarter subclass.");
}
+ @Override
public String toString() {
return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]";
}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java
index cb2ce008aa..0e5f5fd00f 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2010-2019 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
+ *
+ * https://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.core.test.step;
import static org.junit.Assert.assertEquals;
@@ -17,6 +32,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -30,8 +46,9 @@
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -75,7 +92,7 @@ public void setUp() throws Exception {
writer = new SkipWriterStub(dataSource);
processor = new SkipProcessorStub(dataSource);
- factory = new FaultTolerantStepFactoryBean();
+ factory = new FaultTolerantStepFactoryBean<>();
factory.setBeanName("stepName");
factory.setTransactionManager(transactionManager);
@@ -129,17 +146,17 @@ public void testMultithreadedSunnyDay() throws Throwable {
try {
- Step step = (Step) factory.getObject();
+ Step step = factory.getObject();
stepExecution = jobExecution.createStepExecution(factory.getName());
repository.add(stepExecution);
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
- List committed = new ArrayList(writer.getCommitted());
+ List committed = new ArrayList<>(writer.getCommitted());
Collections.sort(committed);
assertEquals("[1, 2, 3, 4, 5]", committed.toString());
- List processed = new ArrayList(processor.getCommitted());
+ List processed = new ArrayList<>(processor.getCommitted());
Collections.sort(processed);
assertEquals("[1, 2, 3, 4, 5]", processed.toString());
assertEquals(0, stepExecution.getSkipCount());
@@ -173,6 +190,8 @@ public void clear() {
counter = -1;
}
+ @Nullable
+ @Override
public synchronized String read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
@@ -185,7 +204,7 @@ public synchronized String read() throws Exception, UnexpectedInputException, Pa
private static class SkipWriterStub implements ItemWriter {
- private List written = new ArrayList();
+ private List written = new ArrayList<>();
private Collection failures = Collections.emptySet();
@@ -197,7 +216,8 @@ public SkipWriterStub(DataSource dataSource) {
public List getCommitted() {
return jdbcTemplate.query("SELECT MESSAGE from ERROR_LOG where STEP_NAME='written'",
- new ParameterizedRowMapper() {
+ new RowMapper() {
+ @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
@@ -209,6 +229,7 @@ public void clear() {
jdbcTemplate.update("DELETE FROM ERROR_LOG where STEP_NAME='written'");
}
+ @Override
public void write(List extends String> items) throws Exception {
for (String item : items) {
written.add(item);
@@ -228,7 +249,7 @@ private static class SkipProcessorStub implements ItemProcessor
private final Log logger = LogFactory.getLog(getClass());
- private List processed = new ArrayList();
+ private List processed = new ArrayList<>();
private JdbcTemplate jdbcTemplate;
@@ -241,7 +262,8 @@ public SkipProcessorStub(DataSource dataSource) {
public List getCommitted() {
return jdbcTemplate.query("SELECT MESSAGE from ERROR_LOG where STEP_NAME='processed'",
- new ParameterizedRowMapper() {
+ new RowMapper() {
+ @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
@@ -253,6 +275,8 @@ public void clear() {
jdbcTemplate.update("DELETE FROM ERROR_LOG where STEP_NAME='processed'");
}
+ @Nullable
+ @Override
public String process(String item) throws Exception {
processed.add(item);
logger.debug("Processed item: "+item);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java
index dd223f94ae..f5603daa73 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java
@@ -1,7 +1,20 @@
+/*
+ * Copyright 2010-2019 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
+ *
+ * https://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.core.test.step;
-import static org.junit.Assert.assertEquals;
-
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -12,7 +25,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
-
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
@@ -20,6 +32,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -33,8 +46,9 @@
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -42,6 +56,8 @@
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
+import static org.junit.Assert.assertEquals;
+
/**
* Tests for {@link FaultTolerantStepFactoryBean}.
*/
@@ -78,7 +94,7 @@ public void setUp() throws Exception {
writer = new SkipWriterStub(dataSource);
processor = new SkipProcessorStub(dataSource);
- factory = new FaultTolerantStepFactoryBean();
+ factory = new FaultTolerantStepFactoryBean<>();
factory.setBeanName("stepName");
factory.setTransactionManager(transactionManager);
@@ -143,7 +159,7 @@ public void testMultithreadedSkipInWriter() throws Throwable {
writer.setFailures("1", "2", "3", "4", "5");
- Step step = (Step) factory.getObject();
+ Step step = factory.getObject();
stepExecution = jobExecution.createStepExecution(factory.getName());
repository.add(stepExecution);
@@ -152,7 +168,7 @@ public void testMultithreadedSkipInWriter() throws Throwable {
assertEquals("[]", writer.getCommitted().toString());
assertEquals("[]", processor.getCommitted().toString());
- List processed = new ArrayList(processor.getProcessed());
+ List processed = new ArrayList<>(processor.getProcessed());
Collections.sort(processed);
assertEquals("[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]", processed.toString());
assertEquals(5, stepExecution.getSkipCount());
@@ -167,8 +183,9 @@ public void testMultithreadedSkipInWriter() throws Throwable {
}
+ @SuppressWarnings("unchecked")
private Map, Boolean> getExceptionMap(Class extends Throwable>... args) {
- Map, Boolean> map = new HashMap, Boolean>();
+ Map, Boolean> map = new HashMap<>();
for (Class extends Throwable> arg : args) {
map.put(arg, true);
}
@@ -194,6 +211,8 @@ public void clear() {
counter = -1;
}
+ @Nullable
+ @Override
public synchronized String read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
@@ -206,7 +225,7 @@ public synchronized String read() throws Exception, UnexpectedInputException, Pa
private static class SkipWriterStub implements ItemWriter {
- private List written = new CopyOnWriteArrayList();
+ private List written = new CopyOnWriteArrayList<>();
private Collection failures = Collections.emptySet();
@@ -222,7 +241,8 @@ public void setFailures(String... failures) {
public List getCommitted() {
return jdbcTemplate.query("SELECT MESSAGE from ERROR_LOG where STEP_NAME='written'",
- new ParameterizedRowMapper() {
+ new RowMapper() {
+ @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
@@ -234,6 +254,7 @@ public void clear() {
jdbcTemplate.update("DELETE FROM ERROR_LOG where STEP_NAME='written'");
}
+ @Override
public void write(List extends String> items) throws Exception {
for (String item : items) {
written.add(item);
@@ -253,7 +274,7 @@ private static class SkipProcessorStub implements ItemProcessor
private final Log logger = LogFactory.getLog(getClass());
- private List processed = new CopyOnWriteArrayList();
+ private List processed = new CopyOnWriteArrayList<>();
private JdbcTemplate jdbcTemplate;
@@ -273,7 +294,8 @@ public List getProcessed() {
public List getCommitted() {
return jdbcTemplate.query("SELECT MESSAGE from ERROR_LOG where STEP_NAME='processed'",
- new ParameterizedRowMapper() {
+ new RowMapper() {
+ @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
@@ -285,6 +307,8 @@ public void clear() {
jdbcTemplate.update("DELETE FROM ERROR_LOG where STEP_NAME='processed'");
}
+ @Nullable
+ @Override
public String process(String item) throws Exception {
processed.add(item);
logger.debug("Processed item: " + item);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java
new file mode 100644
index 0000000000..50d6aa74c5
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java
@@ -0,0 +1,226 @@
+package org.springframework.batch.core.test.step;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.step.builder.FaultTolerantStepBuilder;
+import org.springframework.batch.core.step.skip.SkipLimitExceededException;
+import org.springframework.batch.core.step.skip.SkipPolicy;
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.support.ListItemReader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.Nullable;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for fault tolerant {@link org.springframework.batch.core.step.item.ChunkOrientedTasklet}.
+ */
+@ContextConfiguration(locations = "/simple-job-launcher-context.xml")
+@RunWith(SpringJUnit4ClassRunner.class)
+public class FaultTolerantStepIntegrationTests {
+
+ private static final int TOTAL_ITEMS = 30;
+ private static final int CHUNK_SIZE = TOTAL_ITEMS;
+
+ @Autowired
+ private JobRepository jobRepository;
+
+ @Autowired
+ private PlatformTransactionManager transactionManager;
+
+ private SkipPolicy skipPolicy;
+
+ private FaultTolerantStepBuilder stepBuilder;
+
+ @Before
+ public void setUp() {
+ ItemReader itemReader = new ListItemReader<>(createItems());
+ ItemProcessor itemProcessor = item -> item > 20 ? null : item;
+ ItemWriter itemWriter = chunk -> {
+ if (chunk.contains(1)) {
+ throw new IllegalArgumentException();
+ }
+ };
+ skipPolicy = new SkipIllegalArgumentExceptionSkipPolicy();
+ stepBuilder = new StepBuilderFactory(jobRepository, transactionManager).get("step")
+ .chunk(CHUNK_SIZE)
+ .reader(itemReader)
+ .processor(itemProcessor)
+ .writer(itemWriter)
+ .faultTolerant();
+ }
+
+ @Test
+ public void testFilterCountWithTransactionalProcessorWhenSkipInWrite() throws Exception {
+ // Given
+ Step step = stepBuilder
+ .skipPolicy(skipPolicy)
+ .build();
+
+ // When
+ StepExecution stepExecution = execute(step);
+
+ // Then
+ assertEquals(TOTAL_ITEMS, stepExecution.getReadCount());
+ assertEquals(10, stepExecution.getFilterCount());
+ assertEquals(19, stepExecution.getWriteCount());
+ assertEquals(1, stepExecution.getWriteSkipCount());
+ }
+
+ @Test
+ public void testFilterCountWithNonTransactionalProcessorWhenSkipInWrite() throws Exception {
+ // Given
+ Step step = stepBuilder
+ .skipPolicy(skipPolicy)
+ .processorNonTransactional()
+ .build();
+
+ // When
+ StepExecution stepExecution = execute(step);
+
+ // Then
+ assertEquals(TOTAL_ITEMS, stepExecution.getReadCount());
+ assertEquals(10, stepExecution.getFilterCount());
+ assertEquals(19, stepExecution.getWriteCount());
+ assertEquals(1, stepExecution.getWriteSkipCount());
+ }
+
+ @Test
+ public void testFilterCountOnRetryWithTransactionalProcessorWhenSkipInWrite() throws Exception {
+ // Given
+ Step step = stepBuilder
+ .retry(IllegalArgumentException.class)
+ .retryLimit(2)
+ .skipPolicy(skipPolicy)
+ .build();
+
+ // When
+ StepExecution stepExecution = execute(step);
+
+ // Then
+ assertEquals(TOTAL_ITEMS, stepExecution.getReadCount());
+ // filter count is expected to be counted on each retry attempt
+ assertEquals(20, stepExecution.getFilterCount());
+ assertEquals(19, stepExecution.getWriteCount());
+ assertEquals(1, stepExecution.getWriteSkipCount());
+ }
+
+ @Test
+ public void testFilterCountOnRetryWithNonTransactionalProcessorWhenSkipInWrite() throws Exception {
+ // Given
+ Step step = stepBuilder
+ .retry(IllegalArgumentException.class)
+ .retryLimit(2)
+ .skipPolicy(skipPolicy)
+ .processorNonTransactional()
+ .build();
+
+ // When
+ StepExecution stepExecution = execute(step);
+
+ // Then
+ assertEquals(TOTAL_ITEMS, stepExecution.getReadCount());
+ // filter count is expected to be counted on each retry attempt
+ assertEquals(20, stepExecution.getFilterCount());
+ assertEquals(19, stepExecution.getWriteCount());
+ assertEquals(1, stepExecution.getWriteSkipCount());
+ }
+
+ @Test(timeout = 3000)
+ public void testExceptionInProcessDuringChunkScan() throws Exception {
+ // Given
+ ListItemReader itemReader = new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
+
+ ItemProcessor itemProcessor = new ItemProcessor() {
+ private int cpt;
+
+ @Nullable
+ @Override
+ public Integer process(Integer item) throws Exception {
+ cpt++;
+ if (cpt == 7) { // item 2 succeeds the first time but fails during the scan
+ throw new Exception("Error during process");
+ }
+ return item;
+ }
+ };
+
+ ItemWriter itemWriter = new ItemWriter() {
+ private int cpt;
+
+ @Override
+ public void write(List extends Integer> items) throws Exception {
+ cpt++;
+ if (cpt == 1) {
+ throw new Exception("Error during write");
+ }
+ }
+ };
+
+ Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step")
+ .chunk(5)
+ .reader(itemReader)
+ .processor(itemProcessor)
+ .writer(itemWriter)
+ .faultTolerant()
+ .skip(Exception.class)
+ .skipLimit(3)
+ .build();
+
+ // When
+ StepExecution stepExecution = execute(step);
+
+ // Then
+ assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
+ assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus());
+ assertEquals(7, stepExecution.getReadCount());
+ assertEquals(6, stepExecution.getWriteCount());
+ assertEquals(1, stepExecution.getProcessSkipCount());
+ }
+
+ private List createItems() {
+ List items = new ArrayList<>(TOTAL_ITEMS);
+ for (int i = 1; i <= TOTAL_ITEMS; i++) {
+ items.add(i);
+ }
+ return items;
+ }
+
+ private StepExecution execute(Step step) throws Exception {
+ JobExecution jobExecution = jobRepository.createJobExecution(
+ "job" + Math.random(), new JobParameters());
+ StepExecution stepExecution = jobExecution.createStepExecution("step");
+ jobRepository.add(stepExecution);
+ step.execute(stepExecution);
+ return stepExecution;
+ }
+
+ private class SkipIllegalArgumentExceptionSkipPolicy implements SkipPolicy {
+
+ @Override
+ public boolean shouldSkip(Throwable throwable, int skipCount)
+ throws SkipLimitExceededException {
+ return throwable instanceof IllegalArgumentException;
+ }
+
+ }
+}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanRollbackTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanRollbackTests.java
index cfd47fa1ac..9fc279d253 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanRollbackTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanRollbackTests.java
@@ -1,7 +1,20 @@
+/*
+ * Copyright 2010-2019 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
+ *
+ * https://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.core.test.step;
-import static org.junit.Assert.assertEquals;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -15,6 +28,7 @@
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
+
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
@@ -26,13 +40,14 @@
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
-import org.springframework.batch.item.ParseException;
-import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
+import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
+import static org.junit.Assert.assertEquals;
+
/**
* Tests for {@link FaultTolerantStepFactoryBean}.
*/
@@ -66,7 +81,7 @@ public void setUp() throws Exception {
writer = new SkipWriterStub();
processor = new SkipProcessorStub();
- factory = new FaultTolerantStepFactoryBean();
+ factory = new FaultTolerantStepFactoryBean<>();
factory.setTransactionManager(transactionManager);
factory.setBeanName("stepName");
@@ -104,7 +119,7 @@ public void testMultithreadedSkipInWrite() throws Throwable {
if (i%100==0) {
logger.info("Starting step: "+i);
- repository = new MapJobRepositoryFactoryBean(transactionManager).getJobRepository();
+ repository = new MapJobRepositoryFactoryBean(transactionManager).getObject();
factory.setJobRepository(repository);
jobExecution = repository.createJobExecution("vanillaJob", new JobParameters());
}
@@ -121,7 +136,7 @@ public void testMultithreadedSkipInWrite() throws Throwable {
try {
- Step step = (Step) factory.getObject();
+ Step step = factory.getObject();
stepExecution = jobExecution.createStepExecution(factory.getName());
repository.add(stepExecution);
@@ -129,7 +144,7 @@ public void testMultithreadedSkipInWrite() throws Throwable {
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(5, stepExecution.getSkipCount());
- List processed = new ArrayList(processor.getProcessed());
+ List processed = new ArrayList<>(processor.getProcessed());
Collections.sort(processed);
assertEquals("[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]", processed.toString());
@@ -162,13 +177,14 @@ public void clear() {
counter = -1;
}
- public synchronized String read() throws Exception, UnexpectedInputException, ParseException {
+ @Nullable
+ @Override
+ public synchronized String read() throws Exception {
counter++;
if (counter >= items.length) {
return null;
}
- String item = items[counter];
- return item;
+ return items[counter];
}
}
@@ -176,7 +192,7 @@ private static class SkipWriterStub implements ItemWriter {
private final Log logger = LogFactory.getLog(getClass());
- private List written = new CopyOnWriteArrayList();
+ private List written = new CopyOnWriteArrayList<>();
private Collection failures = Collections.emptySet();
@@ -192,6 +208,7 @@ public void clear() {
written.clear();
}
+ @Override
public void write(List extends String> items) throws Exception {
for (String item : items) {
logger.trace("Writing: "+item);
@@ -211,7 +228,7 @@ private static class SkipProcessorStub implements ItemProcessor
private final Log logger = LogFactory.getLog(getClass());
- private List processed = new CopyOnWriteArrayList();
+ private List processed = new CopyOnWriteArrayList<>();
public List getProcessed() {
return processed;
@@ -221,6 +238,8 @@ public void clear() {
processed.clear();
}
+ @Nullable
+ @Override
public String process(String item) throws Exception {
processed.add(item);
logger.debug("Processed item: "+item);
@@ -228,8 +247,9 @@ public String process(String item) throws Exception {
}
}
+ @SuppressWarnings("unchecked")
private Map, Boolean> getExceptionMap(Class extends Throwable>... args) {
- Map, Boolean> map = new HashMap, Boolean>();
+ Map, Boolean> map = new HashMap<>();
for (Class extends Throwable> arg : args) {
map.put(arg, true);
}
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanTests.java
index 6044d1f138..669b441426 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/MapRepositoryFaultTolerantStepFactoryBeanTests.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2010-2019 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
+ *
+ * https://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.core.test.step;
import static org.junit.Assert.assertEquals;
@@ -27,6 +42,7 @@
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
+import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
@@ -63,7 +79,7 @@ public void setUp() throws Exception {
writer = new SkipWriterStub();
processor = new SkipProcessorStub();
- factory = new FaultTolerantStepFactoryBean();
+ factory = new FaultTolerantStepFactoryBean<>();
factory.setBeanName("stepName");
factory.setTransactionManager(transactionManager);
@@ -98,7 +114,7 @@ public void testMultithreadedSunnyDay() throws Throwable {
if (i%100==0) {
logger.info("Starting step: "+i);
- repository = new MapJobRepositoryFactoryBean(transactionManager).getJobRepository();
+ repository = new MapJobRepositoryFactoryBean(transactionManager).getObject();
factory.setJobRepository(repository);
jobExecution = repository.createJobExecution("vanillaJob", new JobParameters());
}
@@ -113,17 +129,17 @@ public void testMultithreadedSunnyDay() throws Throwable {
try {
- Step step = (Step) factory.getObject();
+ Step step = factory.getObject();
stepExecution = jobExecution.createStepExecution(factory.getName());
repository.add(stepExecution);
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
- List committed = new ArrayList(writer.getWritten());
+ List committed = new ArrayList<>(writer.getWritten());
Collections.sort(committed);
assertEquals("[1, 2, 3, 4, 5]", committed.toString());
- List processed = new ArrayList(processor.getProcessed());
+ List processed = new ArrayList<>(processor.getProcessed());
Collections.sort(processed);
assertEquals("[1, 2, 3, 4, 5]", processed.toString());
assertEquals(0, stepExecution.getSkipCount());
@@ -157,6 +173,8 @@ public void clear() {
counter = -1;
}
+ @Nullable
+ @Override
public synchronized String read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
@@ -169,7 +187,7 @@ public synchronized String read() throws Exception, UnexpectedInputException, Pa
private static class SkipWriterStub implements ItemWriter {
- private List written = new CopyOnWriteArrayList();
+ private List written = new CopyOnWriteArrayList<>();
private Collection failures = Collections.emptySet();
@@ -181,6 +199,7 @@ public void clear() {
written.clear();
}
+ @Override
public void write(List extends String> items) throws Exception {
for (String item : items) {
written.add(item);
@@ -199,7 +218,7 @@ private static class SkipProcessorStub implements ItemProcessor
private final Log logger = LogFactory.getLog(getClass());
- private List processed = new CopyOnWriteArrayList();
+ private List processed = new CopyOnWriteArrayList<>();
public List getProcessed() {
return processed;
@@ -209,6 +228,8 @@ public void clear() {
processed.clear();
}
+ @Nullable
+ @Override
public String process(String item) throws Exception {
processed.add(item);
logger.debug("Processed item: "+item);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests.java
index 47a0e1dc49..7e59b9bdb4 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2009 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -33,6 +33,7 @@
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.lang.Nullable;
/**
* @author Dave Syer
@@ -45,12 +46,13 @@ public class SplitJobMapRepositoryIntegrationTests {
/** Logger */
private final Log logger = LogFactory.getLog(getClass());
+ @SuppressWarnings("resource")
@Test
public void testMultithreadedSplit() throws Throwable {
JobLauncher jobLauncher = null;
Job job = null;
-
+
ClassPathXmlApplicationContext context = null;
for (int i = 0; i < MAX_COUNT; i++) {
@@ -62,8 +64,8 @@ public void testMultithreadedSplit() throws Throwable {
logger.info("Starting job: " + i);
context = new ClassPathXmlApplicationContext(getClass().getSimpleName()
+ "-context.xml", getClass());
- jobLauncher = (JobLauncher) context.getBean("jobLauncher", JobLauncher.class);
- job = (Job) context.getBean("job", Job.class);
+ jobLauncher = context.getBean("jobLauncher", JobLauncher.class);
+ job = context.getBean("job", Job.class);
}
try {
@@ -86,6 +88,8 @@ public static class CountingTasklet implements Tasklet {
private AtomicInteger count = new AtomicInteger(0);
+ @Nullable
+ @Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
contribution.incrementReadCount();
contribution.incrementWriteCount(1);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
index c2df1a748a..6d743b3421 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2014 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
+ * https://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,
@@ -30,7 +30,7 @@
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.support.SerializationUtils;
+import org.springframework.util.SerializationUtils;
/**
* @author Dave Syer
@@ -41,7 +41,7 @@ public class StepExecutionSerializationUtilsTests {
@Test
public void testCycle() throws Exception {
StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(123L,
- "job"), 321L, new JobParameters()), 11L);
+ "job"), 321L, new JobParameters(), null), 11L);
stepExecution.getExecutionContext().put("foo.bar.spam", 123);
StepExecution result = getCopy(stepExecution);
assertEquals(stepExecution, result);
@@ -55,12 +55,13 @@ public void testMultipleCycles() throws Throwable {
int threads = 10;
Executor executor = Executors.newFixedThreadPool(threads);
- CompletionService completionService = new ExecutorCompletionService(executor);
+ CompletionService completionService = new ExecutorCompletionService<>(executor);
for (int i = 0; i < repeats; i++) {
- final JobExecution jobExecution = new JobExecution(new JobInstance(123L, "job"), 321L, new JobParameters());
+ final JobExecution jobExecution = new JobExecution(new JobInstance(123L, "job"), 321L, new JobParameters(), null);
for (int j = 0; j < threads; j++) {
completionService.submit(new Callable() {
+ @Override
public StepExecution call() throws Exception {
final StepExecution stepExecution = jobExecution.createStepExecution("step");
stepExecution.getExecutionContext().put("foo.bar.spam", 123);
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java
new file mode 100644
index 0000000000..543055ac39
--- /dev/null
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014 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
+ *
+ * https://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.core.test.timeout;
+
+import javax.sql.DataSource;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.JobParametersBuilder;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.test.AbstractIntegrationTests;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/timeoutJob.xml" })
+public class TimeoutJobIntegrationTests extends AbstractIntegrationTests {
+
+ /** Logger */
+ @SuppressWarnings("unused")
+ private final Log logger = LogFactory.getLog(getClass());
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ @Qualifier("chunkTimeoutJob")
+ private Job chunkTimeoutJob;
+
+ @Autowired
+ @Qualifier("taskletTimeoutJob")
+ private Job taskletTimeoutJob;
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Test
+ public void testChunkTimeoutShouldFail() throws Exception {
+ JobExecution execution = jobLauncher.run(chunkTimeoutJob, new JobParametersBuilder().addLong("id", System.currentTimeMillis())
+ .toJobParameters());
+ assertEquals(BatchStatus.FAILED, execution.getStatus());
+ }
+
+ @Test
+ public void testTaskletTimeoutShouldFail() throws Exception {
+ JobExecution execution = jobLauncher.run(taskletTimeoutJob, new JobParametersBuilder().addLong("id", System.currentTimeMillis())
+ .toJobParameters());
+ assertEquals(BatchStatus.FAILED, execution.getStatus());
+ }
+
+}
diff --git a/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java b/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java
index 5d4aad94cc..6a730f48c3 100644
--- a/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java
+++ b/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -56,6 +56,7 @@ public void setInitialize(boolean initialize) {
this.initialize = initialize;
}
+ @Override
public void destroy() throws Exception {
if (!initialized) {
return;
@@ -76,8 +77,9 @@ public void destroy() throws Exception {
}
}
+ @Override
public void afterPropertiesSet() throws Exception {
- Assert.notNull(dataSource);
+ Assert.notNull(dataSource, "A DataSource is required");
logger.info("Initializing with scripts: "+Arrays.asList(initScripts));
if (!initialized && initialize) {
try {
@@ -101,15 +103,16 @@ private void doExecuteScript(final Resource scriptResource) {
if (scriptResource == null || !scriptResource.exists())
return;
TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
- transactionTemplate.execute(new TransactionCallback() {
+ transactionTemplate.execute(new TransactionCallback() {
+ @Override
@SuppressWarnings("unchecked")
- public Object doInTransaction(TransactionStatus status) {
+ public Void doInTransaction(TransactionStatus status) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String[] scripts;
try {
scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource
- .getInputStream())), ";");
+ .getInputStream(), "UTF-8")), ";");
}
catch (IOException e) {
throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e);
@@ -134,10 +137,10 @@ public Object doInTransaction(TransactionStatus status) {
}
private String stripComments(List list) {
- StringBuffer buffer = new StringBuffer();
+ StringBuilder buffer = new StringBuilder();
for (String line : list) {
if (!line.startsWith("//") && !line.startsWith("--")) {
- buffer.append(line + "\n");
+ buffer.append(line).append("\n");
}
}
return buffer.toString();
diff --git a/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java b/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java
index 2a16eb3890..f58dca137b 100644
--- a/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java
+++ b/spring-batch-core-tests/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2009-2018 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
+ *
+ * https://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 test.jdbc.datasource;
import java.io.File;
@@ -7,27 +22,29 @@
import org.apache.derby.jdbc.EmbeddedDataSource;
import org.springframework.beans.factory.config.AbstractFactoryBean;
-public class DerbyDataSourceFactoryBean extends AbstractFactoryBean {
+public class DerbyDataSourceFactoryBean extends AbstractFactoryBean {
- private String dataDirectory = "derby-home";
+ private String dataDirectory = "build/derby-home";
public void setDataDirectory(String dataDirectory) {
this.dataDirectory = dataDirectory;
}
- protected Object createInstance() throws Exception {
+ @Override
+ protected DataSource createInstance() throws Exception {
File directory = new File(dataDirectory);
System.setProperty("derby.system.home", directory.getCanonicalPath());
System.setProperty("derby.storage.fileSyncTransactionLog", "true");
System.setProperty("derby.storage.pageCacheSize", "100");
final EmbeddedDataSource ds = new EmbeddedDataSource();
- ds.setDatabaseName("derbydb");
+ ds.setDatabaseName("build/derbydb");
ds.setCreateDatabase("create");
return ds;
}
+ @Override
public Class getObjectType() {
return DataSource.class;
}
diff --git a/spring-batch-core-tests/src/test/resources/applicationContext-test1.xml b/spring-batch-core-tests/src/test/resources/applicationContext-test1.xml
new file mode 100644
index 0000000000..65378b5c71
--- /dev/null
+++ b/spring-batch-core-tests/src/test/resources/applicationContext-test1.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-batch-core-tests/src/test/resources/applicationContext-test2.xml b/spring-batch-core-tests/src/test/resources/applicationContext-test2.xml
new file mode 100644
index 0000000000..8ee9f5826f
--- /dev/null
+++ b/spring-batch-core-tests/src/test/resources/applicationContext-test2.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-batch-core-tests/src/test/resources/batch-derby.properties b/spring-batch-core-tests/src/test/resources/batch-derby.properties
index 380004cd1d..026209f3ef 100644
--- a/spring-batch-core-tests/src/test/resources/batch-derby.properties
+++ b/spring-batch-core-tests/src/test/resources/batch-derby.properties
@@ -1,7 +1,7 @@
# Placeholders batch.*
# for Derby:
batch.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
-batch.jdbc.url=jdbc:derby:derby-home/test;create=true
+batch.jdbc.url=jdbc:derby:build/derby-home/test;create=true
batch.jdbc.user=sa
batch.jdbc.password=
batch.jdbc.testWhileIdle=false
@@ -13,4 +13,5 @@ batch.data.source.init=true
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.DerbyMaxValueIncrementer
batch.database.incrementer.parent=columnIncrementerParent
batch.grid.size=2
-batch.verify.cursor.position=false
\ No newline at end of file
+batch.verify.cursor.position=false
+batch.jdbc.validationQuery=values 1
diff --git a/spring-batch-core-tests/src/test/resources/batch-hsql.properties b/spring-batch-core-tests/src/test/resources/batch-hsql.properties
index 87d2d3919d..7af206ad17 100644
--- a/spring-batch-core-tests/src/test/resources/batch-hsql.properties
+++ b/spring-batch-core-tests/src/test/resources/batch-hsql.properties
@@ -1,7 +1,7 @@
# Placeholders batch.*
# for HSQLDB:
batch.jdbc.driver=org.hsqldb.jdbcDriver
-batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true
+batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true;hsqldb.tx=mvcc
# 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
@@ -16,3 +16,4 @@ batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.Hs
batch.database.incrementer.parent=columnIncrementerParent
batch.grid.size=2
batch.verify.cursor.position=true
+batch.jdbc.validationQuery=SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS
diff --git a/spring-batch-core-tests/src/test/resources/batch-mysql.properties b/spring-batch-core-tests/src/test/resources/batch-mysql.properties
index f7377931f1..1c157a6ed5 100644
--- a/spring-batch-core-tests/src/test/resources/batch-mysql.properties
+++ b/spring-batch-core-tests/src/test/resources/batch-mysql.properties
@@ -10,4 +10,5 @@ batch.data.source.init=false
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer
batch.database.incrementer.parent=columnIncrementerParent
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
-batch.verify.cursor.position=true
\ No newline at end of file
+batch.verify.cursor.position=true
+batch.jdbc.validationQuery=SELECT 1
diff --git a/spring-batch-core-tests/src/test/resources/batch-postgres.properties b/spring-batch-core-tests/src/test/resources/batch-postgres.properties
index 9e47c540f2..32c580e59b 100644
--- a/spring-batch-core-tests/src/test/resources/batch-postgres.properties
+++ b/spring-batch-core-tests/src/test/resources/batch-postgres.properties
@@ -10,7 +10,8 @@ batch.schema.script=classpath:/org/springframework/batch/core/schema-postgresql.
batch.drop.script=classpath:/org/springframework/batch/core/schema-drop-postgresql.sql
batch.business.schema.script=classpath:/business-schema-postgresql.sql
batch.data.source.init=true
-batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer
+batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.PostgresSequenceMaxValueIncrementer
batch.database.incrementer.parent=sequenceIncrementerParent
batch.grid.size=2
batch.verify.cursor.position=true
+batch.jdbc.validationQuery=SELECT 1
diff --git a/spring-batch-core-tests/src/test/resources/data-source-context.xml b/spring-batch-core-tests/src/test/resources/data-source-context.xml
index 250993947a..dbc1c04a90 100644
--- a/spring-batch-core-tests/src/test/resources/data-source-context.xml
+++ b/spring-batch-core-tests/src/test/resources/data-source-context.xml
@@ -1,8 +1,8 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans-3.1.xsd+http://www.springframework.org/schema/util%20https://www.springframework.org/schema/util/spring-util-3.1.xsd">
@@ -17,11 +17,12 @@
-
+
+
diff --git a/spring-batch-core-tests/src/test/resources/expectedOutput.ldif b/spring-batch-core-tests/src/test/resources/expectedOutput.ldif
new file mode 100644
index 0000000000..027fc24d05
--- /dev/null
+++ b/spring-batch-core-tests/src/test/resources/expectedOutput.ldif
@@ -0,0 +1,75 @@
+dn: cn=Bjorn Jensen,ou=Accounting,dc=airius,dc=com
+telephonenumber: +1 408 555 1212
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+sn: Jensen
+cn: Bjorn Jensen
+
+dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
+telephonenumber: +1 408 555 1212
+uid: bjensen
+description: Babs is a big sailing fan, and travels extensively in search of perfect sailing conditions.
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+title: Product Manager, Rod and Reel Division
+sn: Jensen
+cn: Barbara Jensen
+cn: Barbara J Jensen
+cn: Babs Jensen
+
+dn: cn=Gern Jensen,ou=Product Testing,dc=airius,dc=com
+telephonenumber: +1 408 555 1212
+uid: gernj
+description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVlIGlzIGJhc2UtNjQtZW5j
+ b2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdGVyIGluIGl0IChhIENSKS4NICBC
+ eSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQgb3V0IG1vcmUu
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+sn: Jensen
+cn: Gern Jensen
+cn: Gern O Jensen
+
+dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
+ou:: 5Za25qWt6YOo
+ou:: 44GI44GE44GO44KH44GG44G2
+ou: Sales
+description: Japanese office
+objectclass: top
+objectclass: organizationalUnit
+
+dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+givenname:: 44Ot44OJ44OL44O8
+givenname:: 44KN44Gp44Gr44O8
+givenname: Rodney
+sn:: 5bCP56yg5Y6f
+sn:: 44GK44GM44GV44KP44KJ
+sn: Ogasawara
+userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+mail: rogasawara@airius.co.jp
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: rogasawara
+preferredlanguage: ja
+cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+cn:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+cn: Rodney Ogasawara
+title:: 5Za25qWt6YOoIOmDqOmVtw==
+title:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+title: Sales, Director
+
+dn: cn=Horatio Jensen,ou=Product Testing,dc=airius,dc=com
+telephonenumber: +1 408 555 1212
+uid: hjensen
+jpegphoto:< file:///usr/local/directory/photos/hjensen.jpg
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+sn: Jensen
+cn: Horatio Jensen
+cn: Horatio N Jensen
+
diff --git a/spring-batch-core-tests/src/test/resources/log4j.properties b/spring-batch-core-tests/src/test/resources/log4j.properties
index 4f10f29e38..3bcb5f9452 100644
--- a/spring-batch-core-tests/src/test/resources/log4j.properties
+++ b/spring-batch-core-tests/src/test/resources/log4j.properties
@@ -1,7 +1,7 @@
log4j.rootCategory=WARN, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout=org.apache.logging.log4j.core.appender.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.logging.log4j.core.layout.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%L - %m%n
log4j.category.org.apache.activemq=ERROR
diff --git a/spring-batch-core-tests/src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml b/spring-batch-core-tests/src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml
index 60c6f57aec..2fd345bb21 100644
--- a/spring-batch-core-tests/src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml
+++ b/spring-batch-core-tests/src/test/resources/org/springframework/batch/core/test/step/SplitJobMapRepositoryIntegrationTests-context.xml
@@ -1,8 +1,8 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans%20https://www.springframework.org/schema/beans/spring-beans.xsd+http://www.springframework.org/schema/batch%20https://www.springframework.org/schema/batch/spring-batch.xsd">
diff --git a/spring-batch-core-tests/src/test/resources/simple-job-launcher-context.xml b/spring-batch-core-tests/src/test/resources/simple-job-launcher-context.xml
index 3256fcc044..7946b246b0 100644
--- a/spring-batch-core-tests/src/test/resources/simple-job-launcher-context.xml
+++ b/spring-batch-core-tests/src/test/resources/simple-job-launcher-context.xml
@@ -1,11 +1,9 @@
+ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+
,o=Airius
+objectclass: top
+objectclass: organizationalUnit
+ou:: 5Za25qWt6YOo
+# ou::
+ou;lang-ja:: 5Za25qWt6YOo
+# ou;lang-ja::
+ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
+# ou;lang-ja::
+ou;lang-en: Sales
+description: Japanese office
+
+dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+# dn:: uid=,ou=,o=Airius
+userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: rogasawara
+mail: rogasawara@airius.co.jp
+givenname;lang-ja:: 44Ot44OJ44OL44O8
+# givenname;lang-ja::
+sn;lang-ja:: 5bCP56yg5Y6f
+# sn;lang-ja::
+cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn;lang-ja::
+title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
+# title;lang-ja::
+preferredlanguage: ja
+givenname:: 44Ot44OJ44OL44O8
+# givenname::
+sn:: 5bCP56yg5Y6f
+# sn::
+cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn::
+title:: 5Za25qWt6YOoIOmDqOmVtw==
+# title::
+givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
+# givenname;lang-ja;phonetic::
+#
+sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
+# sn;lang-ja;phonetic::
+cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+# cn;lang-ja;phonetic::
+title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+# title;lang-ja;phonetic::
+#
+givenname;lang-en: Rodney
+sn;lang-en: Ogasawara
+cn;lang-en: Rodney Ogasawara
+title;lang-en: Sales, Director
+
+
+#
+# Example 5: An LDIF file containing an invalid attribute
+#
+
+dn: cn=Harry Jacobs, ou=Product Development, dc=airius, dc=com
+objectClass: top
+objectClass: person
+cn: Harry Jacobs
+description: :A big sailing fan.
+
+
+#
+# Example 6: A file containing a reference to an external file
+#
+
+dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Horatio Jensen
+cn: Horatio N Jensen
+sn: Jensen
+uid: hjensen
+telephonenumber: +1 408 555 1212
+jpegphoto:< file:///usr/local/directory/photos/hjensen.jpg
+
+
+#
+# Example 7: A file containing a series of change records and comments
+#
+
+# Add a new entry
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+changetype: add
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Fiona Jensen
+sn: Jensen
+uid: fiona
+telephonenumber: +1 408 555 1212
+jpegphoto:< file:///usr/local/directory/photos/fiona.jpg
+
+# Delete an existing entry
+dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+changetype: delete
+
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+
+
+# Modify an entry: add an additional value to the postaladdress
+# attribute, completely delete the description attribute, replace
+# the telephonenumber attribute with two values, and delete a specific
+# value from the facsimiletelephonenumber attribute
+dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+
+# Modify an entry: replace the postaladdress attribute with an empty
+# set of values (which will cause the attribute to be removed), and
+# delete the entire description attribute. Note that the first will
+# always succeed, while the second will only succeed if at least
+# one value for the description attribute is present.
+dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com
+changetype: modify
+replace: postaladdress
+-
+delete: description
+-
+
+
+#
+# Example 8: An LDIF file containing a change record with a control
+#
+
+# Delete an entry. The operation will attach the LDAPv3
+# Tree Delete Control defined in [9]. The criticality
+# field is "true" and the controlValue field is
+# absent, as required by [9].
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805 true
+changetype: delete
diff --git a/spring-batch-core-tests/template.mf b/spring-batch-core-tests/template.mf
deleted file mode 100755
index 610f374d6c..0000000000
--- a/spring-batch-core-tests/template.mf
+++ /dev/null
@@ -1,11 +0,0 @@
-Manifest-Version: 1.0
-Bundle-SymbolicName: org.springframework.batch.core.tests
-Bundle-Name: Spring Batch Core Tests
-Bundle-Vendor: Spring
-Bundle-Version: ${version}
-Bundle-ManifestVersion: 2
-Ignored-Existing-Headers:
- Import-Package,
- Export-Package
-Import-Template:
- *;version="0"
diff --git a/spring-batch-core/.springBeans b/spring-batch-core/.springBeans
index 2fe6e96d3a..b0422b610b 100644
--- a/spring-batch-core/.springBeans
+++ b/spring-batch-core/.springBeans
@@ -1,118 +1,209 @@
-
-
- 1
-
-
-
-
-
-
- src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml
- src/test/resources/org/springframework/batch/core/launch/support/job.xml
- src/test/resources/org/springframework/batch/core/launch/support/test-environment.xml
- src/test/resources/org/springframework/batch/core/launch/support/2jobs.xml
- src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml
- src/test/resources/org/springframework/batch/core/launch/support/job2.xml
- src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml
- src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry.xml
- src/test/resources/org/springframework/batch/core/configuration/support/trivial-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/BranchStepJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/OneStepJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/AsyncPlaceholderTargetSourceTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml
- src/test/resources/org/springframework/batch/core/partition/launch-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/MultipleContextPlaceholderTargetSourceTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/PlaceholderTargetSourceTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/SimplePlaceholderTargetSourceTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/SplitJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopeIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserBeanNameTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForJobElementTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForStepElementTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/launch/JobLauncherIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/PlaceholderTargetSourceCustomEditorTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/util/PlaceholderTargetSourceErrorTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/support/child-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementParentAttributeParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/launch/support/error.xml
- src/test/resources/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/FlowJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobParserNextOutOfScopeTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobParserUnreachableStepInFlowTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobParserUnreachableStepTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests-context.xml
- src/test/resources/org/springframework/batch/core/launch/support/launcher-with-environment.xml
- src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml
- src/test/resources/org/springframework/batch/core/resource/ListPreparedStatementSetterTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/NextAttributeMultipleFinalJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/support/parent-context.xml
- src/test/resources/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserBadRetryListenerTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserBadStepListenerTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserCommitIntervalCompletionPolicyTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserCommitIntervalTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserCompletionPolicyTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserNoCommitIntervalOrCompletionPolicyTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopePerformanceTests-context.xml
- src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests-context.xml
- src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalAttributeParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalTransactionalAttributeParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSimpleAttributeParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementTransactionalAttributeParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/FlowStepParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSkipPolicyParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/xml/JobStepParserTests-context.xml
- src/test/resources/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests-context.xml
-
-
-
-
- true
- false
-
- src/test/resources/org/springframework/batch/core/launch/support/job.xml
- src/test/resources/org/springframework/batch/core/launch/support/test-environment.xml
-
-
-
-
+
+
+ 1
+
+
+
+
+
+
+ src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/job.xml
+ src/test/resources/org/springframework/batch/core/launch/support/test-environment.xml
+ src/test/resources/org/springframework/batch/core/launch/support/2jobs.xml
+ src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/job2.xml
+ src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml
+ src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/trivial-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/BranchStepJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/common-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/OneStepJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/partition/launch-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/SplitJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepParserBeanNameTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForJobElementTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForStepElementTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/launch/JobLauncherIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/child-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementParentAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/error.xml
+ src/test/resources/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/FlowJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobParserNextOutOfScopeTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/launcher-with-environment.xml
+ src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml
+ src/test/resources/org/springframework/batch/core/resource/ListPreparedStatementSetterTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/parent-context.xml
+ src/test/resources/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepParserCommitIntervalTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepParserCompletionPolicyTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepParserParentAttributeTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopePerformanceTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalTransactionalAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSimpleAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementTransactionalAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/FlowStepParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSkipPolicyParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobStepParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForJobElementTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForStepElementTests-context.xml
+ src/main/resources/baseContext.xml
+ src/main/resources/beanRefContext.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalSkipAndRetryAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementLateBindingParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementRetryPolicyParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSkipAndRetryAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/ChunkListenerParsingTests-context.xml
+ src/test/resources/META-INF/batch-jobs/contextClosingTests.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionAfterFlow-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionAfterSplit-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionAsFirstStep-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionCustomExitStatus-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionInvalidExitStatus-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionThrowsException-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-decisionValidExitStatus-context.xml
+ src/test/resources/META-INF/batch-jobs/DecisionStepTests-restart-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/default-split-task-executor-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/DefaultUnknownJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/ExceptionHandlingParsingTests-context.xml
+ src/test/resources/META-INF/batch-jobs/FlowParserTests-context.xml
+ src/test/resources/META-INF/batch-jobs/FlowParserTestsStepGetsFailedTransitionWhenNextAttributePresent.xml
+ src/test/resources/META-INF/batch-jobs/FlowParserTestsStepNoOverrideWhenNextAndFailedTransitionElementExists.xml
+ src/test/resources/META-INF/batch-jobs/FlowParserTestsWildcardAndNextAttrJob.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/ItemListenerParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/ItemSkipParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/job-context-with-separate-steps.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/job-context-with-steps.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/JobListenerParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobParserValidatorTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/JobPropertySubstitutionTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopeDestructionCallbackIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopeIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopeNestedIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopePlaceholderIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopeProxyTargetClassIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/JobScopeStartupIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/JsrDecisionParsingTests-context.xml
+ src/test/resources/META-INF/batch-jobs/JsrSplitParsingTests-context.xml
+ src/test/resources/META-INF/batch-jobs/jsrSpringInstanceTests.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/NamespacePrefixedJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/NextAttributeUnknownJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/override_batch.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ParentRetryableLateBindingStepFactoryBeanParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ParentRetryableStepFactoryBeanParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ParentSkippableLateBindingStepFactoryBeanParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ParentSkippableStepFactoryBeanParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/ParentStepFactoryBeanParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepWithFlowParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepWithLateBindingParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepWithNonDefaultTransactionManagerParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/placeholder-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/profiles.xml
+ src/test/resources/org/springframework/batch/core/step/RestartInPriorStepTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/RetryListenerTestBase-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/RetryReadListenerExhausted.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/RetryReadListenerListenerException.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/RetryReadListenerRetryOnce.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/SimpleItemBasedJobParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/SimpleJobParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/SplitNestedJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/StepListenerParsingTests-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeClassIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTestsInheritence-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTestsInterface-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTestsProxyTargetClass-context.xml
+ src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/StepWithPojoListenerJobParserTests-context.xml
+ src/test/resources/org/springframework/batch/core/repository/dao/TablePrefixTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/TaskletParserAdapterTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/TaskletParserBeanPropertiesTests-context.xml
+ src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTest-context.xml
+ src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-loader.xml
+ src/test/resources/org/springframework/batch/core/configuration/support/trivial-context-autoregister.xml
+ src/test/resources/org/springframework/batch/core/jsr/configuration/xml/user-specified-split-task-executor-context.xml
+ java:org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobBuilderConfigurationTests$AnotherConfiguration
+ java:org.springframework.batch.core.jsr.configuration.xml.BatchParserTests$BaseConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobBuilderConfigurationTests$BeansConfigurer
+ java:org.springframework.batch.core.explore.support.SimpleJobExplorerIntegrationTests$Config
+ java:org.springframework.batch.core.configuration.annotation.DataSourceConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobLoaderConfigurationTests$LoaderFactoryConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobLoaderConfigurationTests$LoaderRegistrarConfiguration
+ java:org.springframework.batch.core.configuration.annotation.ModularBatchConfiguration
+ java:org.springframework.batch.core.step.builder.RegisterMultiListenerTests$MultiListenerFaultTolerantTestConfiguration
+ java:org.springframework.batch.core.step.builder.RegisterMultiListenerTests$MultiListenerTestConfiguration
+ java:org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration
+ java:org.springframework.batch.core.configuration.annotation.StepScopeConfigurationTests$StepScopeConfigurationForcingInterfaceProxy
+ java:org.springframework.batch.core.configuration.annotation.StepScopeConfigurationTests$StepScopeConfigurationInjectingProxy
+ java:org.springframework.batch.core.configuration.annotation.StepScopeConfigurationTests$StepScopeConfigurationRequiringProxyTargetClass
+ java:org.springframework.batch.core.configuration.annotation.StepScopeConfigurationTests$StepScopeConfigurationWithDefaults
+ java:org.springframework.batch.core.configuration.annotation.JobLoaderConfigurationTests$TestConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobBuilderConfigurationTests$TestConfiguration
+ java:org.springframework.batch.core.configuration.annotation.JobBuilderConfigurationTests$TestConfigurer
+ java:org.springframework.batch.core.configuration.annotation.JobLoaderConfigurationTests$VanillaConfiguration
+ java:org.springframework.batch.core.configuration.annotation.StepScopeConfiguration
+
+
+
+
+ true
+ false
+
+ src/test/resources/org/springframework/batch/core/launch/support/job.xml
+ src/test/resources/org/springframework/batch/core/launch/support/test-environment.xml
+
+
+
+
+
+
diff --git a/spring-batch-core/build.gradle b/spring-batch-core/build.gradle
new file mode 100644
index 0000000000..3e7271a2d8
--- /dev/null
+++ b/spring-batch-core/build.gradle
@@ -0,0 +1,45 @@
+/**
+ * Generate schema creation and drop scripts for various databases
+ * supported by Spring Batch.
+ *
+ * @author David Syer (original Ant/Maven work)
+ * @author Chris Beams (port to Gradle)
+ */
+task generateSql {
+ group = "Build"
+ description = "Generates schema creation and drop scripts for supported databases."
+
+ configurations { vpp }
+ dependencies { vpp 'foundrylogic.vpp:vpp:2.2.1' }
+
+ def generatedResourcesDir = new File('src/main/resources/org/springframework/batch/core')
+
+ outputs.dir generatedResourcesDir
+
+ ant.typedef(resource: 'foundrylogic/vpp/typedef.properties',
+ classpath: configurations.vpp.asPath)
+ ant.taskdef(resource: 'foundrylogic/vpp/taskdef.properties',
+ classpath: configurations.vpp.asPath)
+
+ doLast {
+ ['db2', 'derby', 'h2', 'hsqldb', 'mysql',
+ 'oracle10g', 'postgresql', 'sqlf', 'sqlserver', 'sybase'].each { dbType ->
+ ant.vppcopy(todir: generatedResourcesDir, overwrite: 'true') {
+ config {
+ context {
+ property key: 'includes', value: 'src/main/sql'
+ property file: "src/main/sql/${dbType}.properties"
+ }
+ engine {
+ property key: 'velocimacro.library', value: "src/main/sql/${dbType}.vpp"
+ }
+ }
+ fileset dir: 'src/main/sql', includes: 'schema*.sql.vpp'
+ mapper type: 'glob', from: '*.sql.vpp', to: "*-${dbType}.sql"
+ }
+ }
+ }
+}
+
+// tie schema generation to the build lifecycle
+//compileJava.dependsOn generateSql
diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml
deleted file mode 100644
index 32fb9dce7c..0000000000
--- a/spring-batch-core/pom.xml
+++ /dev/null
@@ -1,302 +0,0 @@
-
-
- 4.0.0
- spring-batch-core
- jar
- Core
- Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc.
- http://static.springframework.org/spring-batch/${project.artifactId}
-
- org.springframework.batch
- spring-batch-parent
- 2.2.2.BUILD-SNAPSHOT
- ../spring-batch-parent
-
-
-
- org.springframework.batch
- spring-batch-infrastructure
- ${project.version}
-
-
- org.hsqldb
- hsqldb
-
-
- com.h2database
- h2
- 1.2.132
-
-
- commons-io
- commons-io
- test
-
-
- commons-dbcp
- commons-dbcp
- true
- test
-
-
-
-
-
-
- junit
- junit
-
-
- org.aspectj
- aspectjrt
- true
-
-
- org.aspectj
- aspectjweaver
- true
-
-
- cglib
- cglib-nodep
- test
-
-
- com.thoughtworks.xstream
- xstream
-
-
- org.codehaus.jettison
- jettison
-
-
- org.osgi
- osgi_R4_core
- true
-
-
- org.springframework
- spring-aop
-
-
- org.springframework
- spring-beans
-
-
- org.springframework
- spring-context
-
-
- org.springframework
- spring-core
-
-
- org.springframework
- spring-jdbc
- true
-
-
- org.springframework.osgi
- spring-osgi-core
- true
-
-
- org.springframework
- spring-test
- test
-
-
- org.springframework
- spring-tx
-
-
- org.slf4j
- slf4j-log4j12
- true
-
-
- log4j
- log4j
- true
-
-
- org.mockito
- mockito-all
- test
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
- generate-sql
- generate-sources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- run
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- junit:junit
-
-
-
-
-
-
-
-
- org.codehaus.mojo
- emma-maven-plugin
- 1.0-alpha-1
-
-
-
-
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java
index 15e2414dcf..fab23ada7e 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -17,10 +17,12 @@
package org.springframework.batch.core;
/**
- * Enumeration representing the status of a an Execution.
+ * Enumeration representing the status of an Execution.
*
* @author Lucas Ward
* @author Dave Syer
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
*/
public enum BatchStatus {
@@ -76,8 +78,9 @@ public BatchStatus upgradeTo(BatchStatus other) {
return max(this, other);
}
// Both less than or equal to STARTED
- if (this == COMPLETED || other == COMPLETED)
+ if (this == COMPLETED || other == COMPLETED) {
return COMPLETED;
+ }
return max(this, other);
}
@@ -105,6 +108,29 @@ public boolean isLessThanOrEqualTo(BatchStatus other) {
return this.compareTo(other) <= 0;
}
+ /**
+ * Converts the current status to the JSR-352 equivalent
+ *
+ * @return JSR-352 equivalent to the current status
+ */
+ public javax.batch.runtime.BatchStatus getBatchStatus() {
+ if(this == ABANDONED) {
+ return javax.batch.runtime.BatchStatus.ABANDONED;
+ } else if(this == COMPLETED) {
+ return javax.batch.runtime.BatchStatus.COMPLETED;
+ } else if(this == STARTED) {
+ return javax.batch.runtime.BatchStatus.STARTED;
+ } else if(this == STARTING) {
+ return javax.batch.runtime.BatchStatus.STARTING;
+ } else if(this == STOPPED) {
+ return javax.batch.runtime.BatchStatus.STOPPED;
+ } else if(this == STOPPING) {
+ return javax.batch.runtime.BatchStatus.STOPPING;
+ } else {
+ return javax.batch.runtime.BatchStatus.FAILED;
+ }
+ }
+
/**
* Find a BatchStatus that matches the beginning of the given value. If no
* match is found, return COMPLETED as the default because has is low
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java
index 8596bd4d37..b9ab2f6051 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -19,11 +19,12 @@
/**
* Listener interface for the lifecycle of a chunk. A chunk
- * can be through of as a collection of items that will be
+ * can be thought of as a collection of items that will be
* committed together.
*
* @author Lucas Ward
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
*
*/
public interface ChunkListener extends StepListener {
@@ -49,7 +50,7 @@ public interface ChunkListener extends StepListener {
* after transaction rollback. While the rollback will have occurred,
* transactional resources might still be active and accessible. Due to
* this, data access code within this callback will still "participate" in
- * the original transaction unless it declares that it run in its own
+ * the original transaction unless it declares that it runs in its own
* transaction. Hence: Use PROPAGATION_REQUIRES_NEW for any
* transactional operation that is called from here.
*
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java
index 410037d263..e464f16609 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -24,6 +24,8 @@
import java.util.List;
import java.util.Map;
+import org.springframework.util.Assert;
+
/**
* Default implementation of the {@link JobKeyGenerator} interface.
* This implementation provides a single hash value based on the JobParameters
@@ -31,6 +33,7 @@
* are used in the calculation of the key.
*
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
* @since 2.2
*/
public class DefaultJobKeyGenerator implements JobKeyGenerator {
@@ -42,15 +45,16 @@ public class DefaultJobKeyGenerator implements JobKeyGenerator {
@Override
public String generateKey(JobParameters source) {
+ Assert.notNull(source, "source must not be null");
Map props = source.getParameters();
- StringBuffer stringBuffer = new StringBuffer();
- List keys = new ArrayList(props.keySet());
+ StringBuilder stringBuffer = new StringBuilder();
+ List keys = new ArrayList<>(props.keySet());
Collections.sort(keys);
for (String key : keys) {
JobParameter jobParameter = props.get(key);
if(jobParameter.isIdentifying()) {
String value = jobParameter.getValue()==null ? "" : jobParameter.toString();
- stringBuffer.append(key + "=" + value + ";");
+ stringBuffer.append(key).append("=").append(value).append(";");
}
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java
index 53cd33e1be..47f4032f90 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java
index 66225cdef2..be000c5251 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2014 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
+ * https://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,
@@ -15,12 +15,12 @@
*/
package org.springframework.batch.core;
+import org.springframework.util.StringUtils;
+
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
-import org.springframework.util.StringUtils;
-
/**
* Value object used to carry information about the status of a
* job or step execution.
@@ -95,6 +95,8 @@ public String getExitCode() {
/**
* Getter for the exit description (defaults to blank)
+ *
+ * @return {@link String} containing the exit description.
*/
public String getExitDescription() {
return exitDescription;
@@ -105,8 +107,8 @@ public String getExitDescription() {
* code, and a concatenation of the descriptions. If either value has a
* higher severity then its exit code will be used in the result. In the
* case of equal severity, the exit code is replaced if the new value is
- * alphabetically greater.
- *
+ * alphabetically greater.
+ *
*
* Severity is defined by the exit code:
*
@@ -117,7 +119,7 @@ public String getExitDescription() {
*
Codes beginning with FAILED have severity 5
*
Codes beginning with UNKNOWN have severity 6
*
- * Others have severity 7, so custom exit codes always win.
+ * Others have severity 7, so custom exit codes always win.
*
* If the input is null just return this.
*
@@ -138,7 +140,8 @@ public ExitStatus and(ExitStatus status) {
/**
* @param status an {@link ExitStatus} to compare
- * @return 1,0,-1 according to the severity and exit code
+ * @return greater than zero, 0, less than zero according to the severity and exit code
+ * @see java.lang.Comparable
*/
@Override
public int compareTo(ExitStatus status) {
@@ -225,10 +228,10 @@ public ExitStatus replaceExitCode(String code) {
/**
* Check if this status represents a running process.
*
- * @return true if the exit code is "RUNNING" or "UNKNOWN"
+ * @return true if the exit code is "EXECUTING" or "UNKNOWN"
*/
public boolean isRunning() {
- return "RUNNING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode);
+ return "EXECUTING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode);
}
/**
@@ -241,7 +244,7 @@ public boolean isRunning() {
* description
*/
public ExitStatus addExitDescription(String description) {
- StringBuffer buffer = new StringBuffer();
+ StringBuilder buffer = new StringBuilder();
boolean changed = StringUtils.hasText(description) && !exitDescription.equals(description);
if (StringUtils.hasText(exitDescription)) {
buffer.append(exitDescription);
@@ -259,7 +262,7 @@ public ExitStatus addExitDescription(String description) {
* Extract the stack trace from the throwable provided and append it to
* the exist description.
*
- * @param throwable
+ * @param throwable {@link Throwable} instance containing the stack trace.
* @return a new ExitStatus with the stack trace appended
*/
public ExitStatus addExitDescription(Throwable throwable) {
@@ -269,4 +272,17 @@ public ExitStatus addExitDescription(Throwable throwable) {
return addExitDescription(message);
}
+ /**
+ * @param status the exit code to be evaluated
+ * @return true if the value matches a known exit code
+ */
+ public static boolean isNonDefaultExitStatus(ExitStatus status) {
+ return status == null || status.getExitCode() == null ||
+ status.getExitCode().equals(ExitStatus.COMPLETED.getExitCode()) ||
+ status.getExitCode().equals(ExitStatus.EXECUTING.getExitCode()) ||
+ status.getExitCode().equals(ExitStatus.FAILED.getExitCode()) ||
+ status.getExitCode().equals(ExitStatus.NOOP.getExitCode()) ||
+ status.getExitCode().equals(ExitStatus.STOPPED.getExitCode()) ||
+ status.getExitCode().equals(ExitStatus.UNKNOWN.getExitCode());
+ }
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java
index 544ec5e5f8..8000ef17e7 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -16,6 +16,7 @@
package org.springframework.batch.core;
import org.springframework.batch.item.ItemProcessor;
+import org.springframework.lang.Nullable;
/**
* Listener interface for the processing of an item. Implementations
@@ -24,6 +25,7 @@
* exceptions thrown by the processor.
*
* @author Dave Syer
+ * @author Mahmoud Ben Hassine
*
*/
public interface ItemProcessListener extends StepListener {
@@ -37,13 +39,13 @@ public interface ItemProcessListener extends StepListener {
/**
* Called after {@link ItemProcessor#process(Object)} returns. If the
- * processor returns null, this method will still be called, with
- * a null result, allowing for notification of 'filtered' items.
+ * processor returns {@code null}, this method will still be called, with
+ * a {code null} result, allowing for notification of 'filtered' items.
*
* @param item to be processed
* @param result of processing
*/
- void afterProcess(T item, S result);
+ void afterProcess(T item, @Nullable S result);
/**
* Called if an exception was thrown from {@link ItemProcessor#process(Object)}.
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java
index 72ff04c874..8495d3250c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2008 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -22,6 +22,7 @@
* Listener interface around the reading of an item.
*
* @author Lucas Ward
+ * @author Mahmoud Ben Hassine
*
*/
public interface ItemReadListener extends StepListener {
@@ -32,7 +33,9 @@ public interface ItemReadListener extends StepListener {
void beforeRead();
/**
- * Called after {@link ItemReader#read()}
+ * Called after {@link ItemReader#read()}.
+ * This method is called only for actual items (ie it is not called when the
+ * reader returns null).
*
* @param item returned from read()
*/
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java
index 755ee66599..7fda29adcf 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -21,9 +21,21 @@
import org.springframework.batch.item.ItemWriter;
/**
+ *
* Listener interface for the writing of items. Implementations
* of this interface will be notified before, after, and in case
* of any exception thrown while writing a list of items.
+ *
+ *
+ *
+ * Note: This listener is designed to work around the
+ * lifecycle of an item. This means that each method should be
+ * called once within the lifecycle of an item and in fault
+ * tolerant scenarios, any transactional work that is done in
+ * one of these methods would be rolled back and not re-applied.
+ * Because of this, it is recommended to not perform any logic
+ * using this listener that participates in a transaction.
+ *
*
* @author Lucas Ward
*
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java
index f6c5cafaf7..3f57f02136 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -15,6 +15,8 @@
*/
package org.springframework.batch.core;
+import org.springframework.lang.Nullable;
+
/**
* Batch domain object representing a job. Job is an explicit abstraction
* representing the configuration of a job specified by a developer. It should
@@ -22,7 +24,7 @@
* step.
*
* @author Dave Syer
- *
+ * @author Mahmoud Ben Hassine
*/
public interface Job {
@@ -47,11 +49,12 @@ public interface Job {
/**
* If clients need to generate new parameters for the next execution in a
- * sequence they can use this incrementer. The return value may be null, in
- * the case that this job does not have a natural sequence.
+ * sequence they can use this incrementer. The return value may be {@code null},
+ * in the case that this job does not have a natural sequence.
*
* @return in incrementer to be used for creating new parameters
*/
+ @Nullable
JobParametersIncrementer getJobParametersIncrementer();
/**
@@ -60,8 +63,8 @@ public interface Job {
* the execution.
*
* @return a validator that can be used to check parameter values (never
- * null)
+ * {@code null})
*/
JobParametersValidator getJobParametersValidator();
-}
\ No newline at end of file
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
index ba50b838fe..0618edef0c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -23,18 +23,21 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CopyOnWriteArraySet;
import org.springframework.batch.item.ExecutionContext;
+import org.springframework.lang.Nullable;
/**
* Batch domain object representing the execution of a job.
*
* @author Lucas Ward
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ * @author Dimitrios Liapis
*
*/
@SuppressWarnings("serial")
@@ -44,7 +47,7 @@ public class JobExecution extends Entity {
private JobInstance jobInstance;
- private volatile Collection stepExecutions = new CopyOnWriteArraySet();
+ private volatile Collection stepExecutions = Collections.synchronizedSet(new LinkedHashSet<>());
private volatile BatchStatus status = BatchStatus.STARTING;
@@ -60,35 +63,68 @@ public class JobExecution extends Entity {
private volatile ExecutionContext executionContext = new ExecutionContext();
- private transient volatile List failureExceptions = new CopyOnWriteArrayList();
+ private transient volatile List failureExceptions = new CopyOnWriteArrayList<>();
+
+ private final String jobConfigurationName;
+
+ public JobExecution(JobExecution original) {
+ this.jobParameters = original.getJobParameters();
+ this.jobInstance = original.getJobInstance();
+ this.stepExecutions = original.getStepExecutions();
+ this.status = original.getStatus();
+ this.startTime = original.getStartTime();
+ this.createTime = original.getCreateTime();
+ this.endTime = original.getEndTime();
+ this.lastUpdated = original.getLastUpdated();
+ this.exitStatus = original.getExitStatus();
+ this.executionContext = original.getExecutionContext();
+ this.failureExceptions = original.getFailureExceptions();
+ this.jobConfigurationName = original.getJobConfigurationName();
+ this.setId(original.getId());
+ this.setVersion(original.getVersion());
+ }
/**
* Because a JobExecution isn't valid unless the job is set, this
* constructor is the only valid one from a modeling point of view.
*
* @param job the job of which this execution is a part
+ * @param id {@link Long} that represents the id for the JobExecution.
+ * @param jobParameters {@link JobParameters} instance for this JobExecution.
+ * @param jobConfigurationName {@link String} instance that represents the
+ * job configuration name (used with JSR-352).
*/
- public JobExecution(JobInstance job, Long id, JobParameters jobParameters) {
+ public JobExecution(JobInstance job, Long id, @Nullable JobParameters jobParameters, String jobConfigurationName) {
super(id);
this.jobInstance = job;
this.jobParameters = jobParameters == null ? new JobParameters() : jobParameters;
+ this.jobConfigurationName = jobConfigurationName;
+ }
+
+ public JobExecution(JobInstance job, JobParameters jobParameters, String jobConfigurationName) {
+ this(job, null, jobParameters, jobConfigurationName);
+ }
+
+ public JobExecution(Long id, JobParameters jobParameters, String jobConfigurationName) {
+ this(null, id, jobParameters, jobConfigurationName);
}
/**
* Constructor for transient (unsaved) instances.
*
* @param job the enclosing {@link JobInstance}
+ * @param jobParameters {@link JobParameters} instance for this JobExecution.
*/
public JobExecution(JobInstance job, JobParameters jobParameters) {
- this(job, null, jobParameters);
+ this(job, null, jobParameters, null);
}
public JobExecution(Long id, JobParameters jobParameters) {
- this(null, id, jobParameters);
+ this(null, id, jobParameters, null);
}
public JobExecution(Long id) {
- this(null, id, null);
+ this(null, id, null, null);
}
public JobParameters getJobParameters() {
@@ -153,7 +189,7 @@ public Long getJobId() {
}
/**
- * @param exitStatus
+ * @param exitStatus {@link ExitStatus} instance to be used for job execution.
*/
public void setExitStatus(ExitStatus exitStatus) {
this.exitStatus = exitStatus;
@@ -179,12 +215,14 @@ public JobInstance getJobInstance() {
* @return the step executions that were registered
*/
public Collection getStepExecutions() {
- return Collections.unmodifiableList(new ArrayList(stepExecutions));
+ return Collections.unmodifiableList(new ArrayList<>(stepExecutions));
}
/**
* Register a step execution with the current job execution.
* @param stepName the name of the step the new execution is associated with
+ * @return {@link StepExecution} an empty {@code StepExecution} associated with this
+ * {@code JobExecution}.
*/
public StepExecution createStepExecution(String stepName) {
StepExecution stepExecution = new StepExecution(stepName, this);
@@ -196,10 +234,11 @@ public StepExecution createStepExecution(String stepName) {
* Test if this {@link JobExecution} indicates that it is running. It should
* be noted that this does not necessarily mean that it has been persisted
* as such yet.
- * @return true if the end time is null
+ *
+ * @return true if the end time is null and the start time is not null
*/
public boolean isRunning() {
- return endTime == null;
+ return startTime != null && endTime == null;
}
/**
@@ -256,10 +295,14 @@ public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
+ public String getJobConfigurationName() {
+ return this.jobConfigurationName;
+ }
+
/**
* Package private method for re-constituting the step executions from
* existing instances.
- * @param stepExecution
+ * @param stepExecution execution to be added
*/
void addStepExecution(StepExecution stepExecution) {
stepExecutions.add(stepExecution);
@@ -278,7 +321,7 @@ public Date getLastUpdated() {
/**
* Set the last time this JobExecution was updated.
*
- * @param lastUpdated
+ * @param lastUpdated {@link Date} instance to mark job execution's lastUpdated attribute.
*/
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
@@ -291,7 +334,7 @@ public List getFailureExceptions() {
/**
* Add the provided throwable to the failure exception list.
*
- * @param t
+ * @param t {@link Throwable} instance to be added failure exception list.
*/
public synchronized void addFailureException(Throwable t) {
this.failureExceptions.add(t);
@@ -301,26 +344,31 @@ public synchronized void addFailureException(Throwable t) {
* Return all failure causing exceptions for this JobExecution, including
* step executions.
*
- * @return List containing all exceptions causing failure for
+ * @return List<Throwable> containing all exceptions causing failure for
* this JobExecution.
*/
public synchronized List getAllFailureExceptions() {
- Set allExceptions = new HashSet(failureExceptions);
+ Set allExceptions = new HashSet<>(failureExceptions);
for (StepExecution stepExecution : stepExecutions) {
allExceptions.addAll(stepExecution.getFailureExceptions());
}
- return new ArrayList(allExceptions);
+ return new ArrayList<>(allExceptions);
}
/**
- * Deserialise and ensure transient fields are re-instantiated when read
- * back
+ * Deserialize and ensure transient fields are re-instantiated when read
+ * back.
+ *
+ * @param stream instance of {@link ObjectInputStream}.
+ *
+ * @throws IOException thrown if error occurs during read.
+ * @throws ClassNotFoundException thrown if class is not found.
*/
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
- failureExceptions = new ArrayList();
+ failureExceptions = new ArrayList<>();
}
/*
@@ -345,5 +393,4 @@ public void addStepExecutions(List stepExecutions) {
this.stepExecutions.addAll(stepExecutions);
}
}
-
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java
index 5e87b63049..471d1500cc 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -24,6 +24,7 @@
* @author Dave Syer
*
*/
+@SuppressWarnings("serial")
public class JobExecutionException extends Exception {
/**
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java
index 1cd2fd2b4a..52a24f1227 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java
index dfe83d5fee..fb64606968 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -23,34 +23,37 @@
* JobInstance can be restarted multiple times in case of execution failure and
* it's lifecycle ends with first successful execution.
*
- * Trying to execute an existing JobIntance that has already completed
+ * Trying to execute an existing JobInstance that has already completed
* successfully will result in error. Error will be raised also for an attempt
* to restart a failed JobInstance if the Job is not restartable.
*
* @see Job
* @see JobParameters
* @see JobExecution
+ * @see javax.batch.runtime.JobInstance
*
* @author Lucas Ward
* @author Dave Syer
* @author Robert Kasanicky
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
*
*/
@SuppressWarnings("serial")
-public class JobInstance extends Entity {
+public class JobInstance extends Entity implements javax.batch.runtime.JobInstance{
private final String jobName;
public JobInstance(Long id, String jobName) {
super(id);
- Assert.hasLength(jobName);
+ Assert.hasLength(jobName, "A jobName is required");
this.jobName = jobName;
}
/**
* @return the job name. (Equivalent to getJob().getName())
*/
+ @Override
public String getJobName() {
return jobName;
}
@@ -60,4 +63,8 @@ public String toString() {
return super.toString() + ", Job=[" + jobName + "]";
}
+ @Override
+ public long getInstanceId() {
+ return super.getId();
+ }
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java
index 8d2ba0d51b..8386de9dde 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -28,6 +28,7 @@
* @author Dave Syer
*
*/
+@SuppressWarnings("serial")
public class JobInterruptedException extends JobExecutionException {
private BatchStatus status = BatchStatus.STOPPED;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java
index 54e0ba200c..e6008b3b12 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2013-2013 the original author or authors.
+ * Copyright 2013-2018 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
+ * https://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,
@@ -20,6 +20,7 @@
* unique {@link JobInstance}.
*
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
*
* @param The type of the source data used to calculate the key.
* @since 2.2
@@ -29,7 +30,7 @@ public interface JobKeyGenerator {
/**
* Method to generate the unique key used to identify a job instance.
*
- * @param source Source information used to generate the key
+ * @param source Source information used to generate the key (must not be {@code null})
*
* @return a unique string identifying the job based on the information
* supplied
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java
index 8938876741..199e64c8bd 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -42,6 +42,8 @@ public class JobParameter implements Serializable {
/**
* Construct a new JobParameter as a String.
+ * @param parameter {@link String} instance.
+ * @param identifying true if JobParameter should be identifying.
*/
public JobParameter(String parameter, boolean identifying) {
this.parameter = parameter;
@@ -52,7 +54,8 @@ public JobParameter(String parameter, boolean identifying) {
/**
* Construct a new JobParameter as a Long.
*
- * @param parameter
+ * @param parameter {@link Long} instance.
+ * @param identifying true if JobParameter should be identifying.
*/
public JobParameter(Long parameter, boolean identifying) {
this.parameter = parameter;
@@ -63,7 +66,8 @@ public JobParameter(Long parameter, boolean identifying) {
/**
* Construct a new JobParameter as a Date.
*
- * @param parameter
+ * @param parameter {@link Date} instance.
+ * @param identifying true if JobParameter should be identifying.
*/
public JobParameter(Date parameter, boolean identifying) {
this.parameter = parameter;
@@ -74,7 +78,8 @@ public JobParameter(Date parameter, boolean identifying) {
/**
* Construct a new JobParameter as a Double.
*
- * @param parameter
+ * @param parameter {@link Double} instance.
+ * @param identifying true if JobParameter should be identifying.
*/
public JobParameter(Double parameter, boolean identifying) {
this.parameter = parameter;
@@ -85,6 +90,8 @@ public JobParameter(Double parameter, boolean identifying) {
/**
* Construct a new JobParameter as a String.
+ *
+ * @param parameter {@link String} instance.
*/
public JobParameter(String parameter) {
this.parameter = parameter;
@@ -95,7 +102,7 @@ public JobParameter(String parameter) {
/**
* Construct a new JobParameter as a Long.
*
- * @param parameter
+ * @param parameter {@link Long} instance.
*/
public JobParameter(Long parameter) {
this.parameter = parameter;
@@ -106,7 +113,7 @@ public JobParameter(Long parameter) {
/**
* Construct a new JobParameter as a Date.
*
- * @param parameter
+ * @param parameter {@link Date} instance.
*/
public JobParameter(Date parameter) {
this.parameter = parameter;
@@ -117,7 +124,7 @@ public JobParameter(Date parameter) {
/**
* Construct a new JobParameter as a Double.
*
- * @param parameter
+ * @param parameter {@link Double} instance.
*/
public JobParameter(Double parameter) {
this.parameter = parameter;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java
index e62ba71c10..74502ef669 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -20,6 +20,9 @@
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.lang.Nullable;
/**
* Value object representing runtime parameters to a batch job. Because the
@@ -34,6 +37,7 @@
*
* @author Lucas Ward
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
* @since 1.0
*/
@SuppressWarnings("serial")
@@ -42,25 +46,26 @@ public class JobParameters implements Serializable {
private final Map parameters;
public JobParameters() {
- this.parameters = new LinkedHashMap();
+ this.parameters = new LinkedHashMap<>();
}
public JobParameters(Map parameters) {
- this.parameters = new LinkedHashMap(parameters);
+ this.parameters = new LinkedHashMap<>(parameters);
}
/**
* Typesafe Getter for the Long represented by the provided key.
*
* @param key The key to get a value for
- * @return The Long value
+ * @return The Long value or {@code null} if the key is absent
*/
+ @Nullable
public Long getLong(String key){
if (!parameters.containsKey(key)) {
- return 0L;
+ return null;
}
Object value = parameters.get(key).getValue();
- return value==null ? 0L : ((Long)value).longValue();
+ return value==null ? null : ((Long)value).longValue();
}
/**
@@ -71,7 +76,10 @@ public Long getLong(String key){
* @param defaultValue to return if the value doesn't exist
* @return the parameter represented by the provided key, defaultValue
* otherwise.
+ * @deprecated Use {@link JobParameters#getLong(java.lang.String, java.lang.Long)}
+ * instead. This method will be removed in a future release.
*/
+ @Deprecated
public Long getLong(String key, long defaultValue){
if(parameters.containsKey(key)){
return getLong(key);
@@ -81,12 +89,32 @@ public Long getLong(String key, long defaultValue){
}
}
+ /**
+ * Typesafe Getter for the Long represented by the provided key. If the
+ * key does not exist, the default value will be returned.
+ *
+ * @param key to return the value for
+ * @param defaultValue to return if the value doesn't exist
+ * @return the parameter represented by the provided key, defaultValue
+ * otherwise.
+ */
+ @Nullable
+ public Long getLong(String key, @Nullable Long defaultValue){
+ if(parameters.containsKey(key)){
+ return getLong(key);
+ }
+ else{
+ return defaultValue;
+ }
+ }
+
/**
* Typesafe Getter for the String represented by the provided key.
*
* @param key The key to get a value for
- * @return The String value
+ * @return The String value or {@code null} if the key is absent
*/
+ @Nullable
public String getString(String key){
JobParameter value = parameters.get(key);
return value==null ? null : value.toString();
@@ -101,7 +129,8 @@ public String getString(String key){
* @return the parameter represented by the provided key, defaultValue
* otherwise.
*/
- public String getString(String key, String defaultValue){
+ @Nullable
+ public String getString(String key, @Nullable String defaultValue){
if(parameters.containsKey(key)){
return getString(key);
}
@@ -114,14 +143,15 @@ public String getString(String key, String defaultValue){
* Typesafe Getter for the Long represented by the provided key.
*
* @param key The key to get a value for
- * @return The Double value
+ * @return The Double value or {@code null} if the key is absent
*/
+ @Nullable
public Double getDouble(String key){
if (!parameters.containsKey(key)) {
- return 0.0;
+ return null;
}
Double value = (Double)parameters.get(key).getValue();
- return value==null ? 0.0 : value.doubleValue();
+ return value==null ? null : value.doubleValue();
}
/**
@@ -132,7 +162,10 @@ public Double getDouble(String key){
* @param defaultValue to return if the value doesn't exist
* @return the parameter represented by the provided key, defaultValue
* otherwise.
+ * @deprecated Use {@link JobParameters#getDouble(java.lang.String, java.lang.Double)}
+ * instead. This method will be removed in a future release.
*/
+ @Deprecated
public Double getDouble(String key, double defaultValue){
if(parameters.containsKey(key)){
return getDouble(key);
@@ -142,12 +175,33 @@ public Double getDouble(String key, double defaultValue){
}
}
+ /**
+ * Typesafe Getter for the Double represented by the provided key. If the
+ * key does not exist, the default value will be returned.
+ *
+ * @param key to return the value for
+ * @param defaultValue to return if the value doesn't exist
+ * @return the parameter represented by the provided key, defaultValue
+ * otherwise.
+ */
+ @Nullable
+ public Double getDouble(String key, @Nullable Double defaultValue){
+ if(parameters.containsKey(key)){
+ return getDouble(key);
+ }
+ else{
+ return defaultValue;
+ }
+ }
+
/**
* Typesafe Getter for the Date represented by the provided key.
*
* @param key The key to get a value for
- * @return The java.util.Date value
+ * @return The java.util.Date value or {@code null} if the key
+ * is absent
*/
+ @Nullable
public Date getDate(String key){
return this.getDate(key,null);
}
@@ -161,7 +215,8 @@ public Date getDate(String key){
* @return the parameter represented by the provided key, defaultValue
* otherwise.
*/
- public Date getDate(String key, Date defaultValue){
+ @Nullable
+ public Date getDate(String key, @Nullable Date defaultValue){
if(parameters.containsKey(key)){
return (Date)parameters.get(key).getValue();
}
@@ -176,7 +231,7 @@ public Date getDate(String key, Date defaultValue){
* @return an unmodifiable map containing all parameters.
*/
public Map getParameters(){
- return new LinkedHashMap(parameters);
+ return new LinkedHashMap<>(parameters);
}
/**
@@ -209,4 +264,16 @@ public int hashCode() {
public String toString() {
return parameters.toString();
}
+
+ public Properties toProperties() {
+ Properties props = new Properties();
+
+ for (Map.Entry param : parameters.entrySet()) {
+ if(param.getValue() != null) {
+ props.put(param.getKey(), param.getValue().toString());
+ }
+ }
+
+ return props;
+ }
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java
index e4e5de7a54..6b194fb645 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -17,45 +17,86 @@
package org.springframework.batch.core;
import java.util.Date;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Properties;
+import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.util.Assert;
/**
* Helper class for creating {@link JobParameters}. Useful because all
* {@link JobParameter} objects are immutable, and must be instantiated separately
- * to ensure typesafety. Once created, it can be used in the
+ * to ensure type safety. Once created, it can be used in the
* same was a java.lang.StringBuilder (except, order is irrelevant), by adding
* various parameter types and creating a valid {@link JobParameters} once
- * finished.
- *
+ * finished.
+ *
* Using the identifying flag indicates if the parameter will be used
* in the identification of a JobInstance. That flag defaults to true.
*
* @author Lucas Ward
* @author Michael Minella
+ * @author Glenn Renfro
+ * @author Mahmoud Ben Hassine
* @since 1.0
* @see JobParameters
* @see JobParameter
*/
public class JobParametersBuilder {
- private final Map parameterMap;
+ private Map parameterMap;
+
+ private JobExplorer jobExplorer;
/**
* Default constructor. Initializes the builder with empty parameters.
*/
public JobParametersBuilder() {
+ this.parameterMap = new LinkedHashMap<>();
+ }
- this.parameterMap = new LinkedHashMap();
+ /**
+ * @param jobExplorer {@link JobExplorer} used for looking up previous job parameter information
+ */
+ public JobParametersBuilder(JobExplorer jobExplorer) {
+ this.jobExplorer = jobExplorer;
+ this.parameterMap = new LinkedHashMap<>();
}
/**
* Copy constructor. Initializes the builder with the supplied parameters.
+ * @param jobParameters {@link JobParameters} instance used to initialize the builder.
*/
public JobParametersBuilder(JobParameters jobParameters) {
- this.parameterMap = new LinkedHashMap(jobParameters.getParameters());
+ this(jobParameters, null);
+ }
+
+ /**
+ * Constructor to add conversion capabilities to support JSR-352. Per the spec, it is expected that all
+ * keys and values in the provided {@link Properties} instance are Strings
+ *
+ * @param properties the job parameters to be used
+ */
+ public JobParametersBuilder(Properties properties) {
+ this.parameterMap = new LinkedHashMap<>();
+
+ if(properties != null) {
+ for (Map.Entry
- *
*
* For reference, the first example above can be compared to the following Spring XML configuration:
*
@@ -152,6 +193,7 @@
*
*
* @author Dave Syer
+ * @author Mahmoud Ben Hassine
*
*/
@Target(ElementType.TYPE)
@@ -164,6 +206,9 @@
* Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
* you should not create any @Bean Job definitions in this context, but rather supply them in separate (child)
* contexts through an {@link ApplicationContextFactory}.
+ *
+ * @return boolean indicating whether the configuration is going to be
+ * modularized into multiple application contexts. Defaults to false.
*/
boolean modular() default false;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
index b6414d3f51..8aba961b02 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java
new file mode 100644
index 0000000000..ab6507f982
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java
@@ -0,0 +1,53 @@
+/*
+ * 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
+ *
+ * https://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.core.configuration.annotation;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ * Convenient annotation for job scoped beans that defaults the proxy mode, so that it doesn't have to be specified
+ * explicitly on every bean definition. Use this on any @Bean that needs to inject @Values from the job
+ * context, and any bean that needs to share a lifecycle with a job execution (e.g. an JobExecutionListener). E.g.
+ *
Marking a @Bean as @JobScope is equivalent to marking it as @Scope(value="job", proxyMode=TARGET_CLASS)
+ *
+ * @author Michael Minella
+ *
+ * @since 3.0.1
+ *
+ */
+@Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface JobScope {
+
+}
\ No newline at end of file
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java
index 1d52179467..7d5ea1709c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -15,11 +15,10 @@
*/
package org.springframework.batch.core.configuration.annotation;
-import java.util.Collection;
-
import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
import org.springframework.batch.core.configuration.support.DefaultJobLoader;
+import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +27,8 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
+import java.util.Collection;
+
/**
* Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is
* available by implementing the {@link BatchConfigurer} interface.
@@ -65,6 +66,12 @@ public PlatformTransactionManager transactionManager() throws Exception {
return getConfigurer(configurers).getTransactionManager();
}
+ @Override
+ @Bean
+ public JobExplorer jobExplorer() throws Exception {
+ return getConfigurer(configurers).getJobExplorer();
+ }
+
@Bean
public AutomaticJobRegistrar jobRegistrar() throws Exception {
registrar.setJobLoader(new DefaultJobLoader(jobRegistry()));
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java
index b3310a2679..2d0f3f6311 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -15,14 +15,13 @@
*/
package org.springframework.batch.core.configuration.annotation;
-import java.util.concurrent.atomic.AtomicReference;
-
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.target.AbstractLazyCreationTargetSource;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.support.MapJobRegistry;
+import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +30,8 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
+import java.util.concurrent.atomic.AtomicReference;
+
/**
* Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is
* available by implementing the {@link BatchConfigurer} interface. The main components are created as lazy proxies that
@@ -50,13 +51,15 @@ public class SimpleBatchConfiguration extends AbstractBatchConfiguration {
private boolean initialized = false;
- private AtomicReference jobRepository = new AtomicReference();
+ private AtomicReference jobRepository = new AtomicReference<>();
+
+ private AtomicReference jobLauncher = new AtomicReference<>();
- private AtomicReference jobLauncher = new AtomicReference();
+ private AtomicReference jobRegistry = new AtomicReference<>();
- private AtomicReference jobRegistry = new AtomicReference();
+ private AtomicReference transactionManager = new AtomicReference<>();
- private AtomicReference transactionManager = new AtomicReference();
+ private AtomicReference jobExplorer = new AtomicReference<>();
@Override
@Bean
@@ -76,6 +79,12 @@ public JobRegistry jobRegistry() throws Exception {
return createLazyProxy(jobRegistry, JobRegistry.class);
}
+ @Override
+ @Bean
+ public JobExplorer jobExplorer() {
+ return createLazyProxy(jobExplorer, JobExplorer.class);
+ }
+
@Override
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
@@ -84,7 +93,7 @@ public PlatformTransactionManager transactionManager() throws Exception {
private T createLazyProxy(AtomicReference reference, Class type) {
ProxyFactory factory = new ProxyFactory();
- factory.setTargetSource(new ReferenceTargetSource(reference));
+ factory.setTargetSource(new ReferenceTargetSource<>(reference));
factory.addAdvice(new PassthruAdvice());
factory.setInterfaces(new Class>[] { type });
@SuppressWarnings("unchecked")
@@ -107,6 +116,7 @@ protected void initialize() throws Exception {
jobLauncher.set(configurer.getJobLauncher());
transactionManager.set(configurer.getTransactionManager());
jobRegistry.set(new MapJobRegistry());
+ jobExplorer.set(configurer.getJobExplorer());
initialized = true;
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java
index fecca1672f..46fcaccb94 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -45,7 +45,7 @@ public StepBuilderFactory(JobRepository jobRepository, PlatformTransactionManage
* @return a step builder
*/
public StepBuilder get(String name) {
- StepBuilder builder = (StepBuilder) new StepBuilder(name).repository(jobRepository).transactionManager(
+ StepBuilder builder = new StepBuilder(name).repository(jobRepository).transactionManager(
transactionManager);
return builder;
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java
index cee43408f2..893e82ee28 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java
@@ -1,12 +1,27 @@
+/*
+ * 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
+ *
+ * https://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.core.configuration.annotation;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import org.springframework.context.annotation.Scope;
-import org.springframework.context.annotation.ScopedProxyMode;
-
/**
*
* Convenient annotation for step scoped beans that defaults the proxy mode, so that it doesn't have to be specified
@@ -27,7 +42,7 @@
*
* @author Dave Syer
*
- * @Since 2.2
+ * @since 2.2
*
*/
@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/package-info.java
new file mode 100644
index 0000000000..6b876be28c
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Annotations and builder factories for java based configuration
+ *
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ */
+@NonNullApi
+package org.springframework.batch.core.configuration.annotation;
+
+import org.springframework.lang.NonNullApi;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package-info.java
new file mode 100644
index 0000000000..95c8411bae
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Interfaces for registration and location of job configurations.
+ *
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ */
+@NonNullApi
+package org.springframework.batch.core.configuration;
+
+import org.springframework.lang.NonNullApi;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package.html b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package.html
deleted file mode 100644
index 19c3ad676c..0000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-Interfaces for registration and location of job configurations.
-
-
-
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java
index 5c977b7436..1b164844df 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2014 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
+ * https://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,
@@ -17,11 +17,13 @@
package org.springframework.batch.core.configuration.support;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -37,6 +39,7 @@
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
/**
* {@link ApplicationContextFactory} implementation that takes a parent context and a path to the context to create.
@@ -49,7 +52,7 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo
private static final Log logger = LogFactory.getLog(AbstractApplicationContextFactory.class);
- private Object resource;
+ private Object[] resources;
private ConfigurableApplicationContext parent;
@@ -60,17 +63,19 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo
private Collection> beanPostProcessorExcludeClasses;
/**
- * Create a factory instance with the resource specified. The resource is a Spring configuration file or java
- * package containing configuration files.
+ * Create a factory instance with the resource specified. The resources are Spring configuration files or java
+ * packages containing configuration files.
+ *
+ * @param resource resource to be used in the creation of the ApplicationContext.
*/
- public AbstractApplicationContextFactory(Object resource) {
+ public AbstractApplicationContextFactory(Object... resource) {
- this.resource = resource;
- beanFactoryPostProcessorClasses = new ArrayList>();
+ this.resources = resource;
+ beanFactoryPostProcessorClasses = new ArrayList<>();
beanFactoryPostProcessorClasses.add(PropertyPlaceholderConfigurer.class);
beanFactoryPostProcessorClasses.add(PropertySourcesPlaceholderConfigurer.class);
beanFactoryPostProcessorClasses.add(CustomEditorConfigurer.class);
- beanPostProcessorExcludeClasses = new ArrayList>();
+ beanPostProcessorExcludeClasses = new ArrayList<>();
/*
* Assume that a BeanPostProcessor that is BeanFactoryAware must be specific to the parent and remove it from
* the child (e.g. an AutoProxyCreator will not work properly). Unfortunately there might still be a a
@@ -108,7 +113,7 @@ protected final boolean isCopyConfiguration() {
public void setBeanFactoryPostProcessorClasses(
Class extends BeanFactoryPostProcessor>[] beanFactoryPostProcessorClasses) {
- this.beanFactoryPostProcessorClasses = new ArrayList>();
+ this.beanFactoryPostProcessorClasses = new ArrayList<>();
for (int i = 0; i < beanFactoryPostProcessorClasses.length; i++) {
this.beanFactoryPostProcessorClasses.add(beanFactoryPostProcessorClasses[i]);
}
@@ -123,7 +128,7 @@ public void setBeanFactoryPostProcessorClasses(
* @param beanPostProcessorExcludeClasses the classes to set
*/
public void setBeanPostProcessorExcludeClasses(Class>[] beanPostProcessorExcludeClasses) {
- this.beanPostProcessorExcludeClasses = new ArrayList>();
+ this.beanPostProcessorExcludeClasses = new ArrayList<>();
for (int i = 0; i < beanPostProcessorExcludeClasses.length; i++) {
this.beanPostProcessorExcludeClasses.add(beanPostProcessorExcludeClasses[i]);
}
@@ -162,16 +167,16 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
@Override
public ConfigurableApplicationContext createApplicationContext() {
- if (resource == null) {
+ if (resources == null || resources.length == 0) {
return parent;
}
- return createApplicationContext(parent, resource);
+ return createApplicationContext(parent, resources);
}
protected abstract ConfigurableApplicationContext createApplicationContext(ConfigurableApplicationContext parent,
- Object resource);
+ Object... resources);
/**
* Extension point for special subclasses that want to do more complex things with the context prior to refresh. The
@@ -199,23 +204,58 @@ protected void prepareContext(ConfigurableApplicationContext parent, Configurabl
protected void prepareBeanFactory(ConfigurableListableBeanFactory parent,
ConfigurableListableBeanFactory beanFactory) {
if (copyConfiguration && parent != null) {
- beanFactory.copyConfigurationFrom(parent);
- List beanPostProcessors = beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory)
- .getBeanPostProcessors() : new ArrayList();
- for (BeanPostProcessor beanPostProcessor : new ArrayList(beanPostProcessors)) {
- for (Class> cls : beanPostProcessorExcludeClasses) {
- if (cls.isAssignableFrom(beanPostProcessor.getClass())) {
- logger.debug("Removing bean post processor: " + beanPostProcessor + " of type " + cls);
- beanPostProcessors.remove(beanPostProcessor);
- }
+ List parentPostProcessors = new ArrayList<>();
+ List childPostProcessors = new ArrayList<>();
+
+ childPostProcessors.addAll(beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory)
+ .getBeanPostProcessors() : new ArrayList<>());
+ parentPostProcessors.addAll(parent instanceof AbstractBeanFactory ? ((AbstractBeanFactory) parent)
+ .getBeanPostProcessors() : new ArrayList<>());
+
+ try {
+ Class> applicationContextAwareProcessorClass =
+ ClassUtils.forName("org.springframework.context.support.ApplicationContextAwareProcessor",
+ parent.getBeanClassLoader());
+
+ for (BeanPostProcessor beanPostProcessor : new ArrayList<>(parentPostProcessors)) {
+ if (applicationContextAwareProcessorClass.isAssignableFrom(beanPostProcessor.getClass())) {
+ logger.debug("Removing parent ApplicationContextAwareProcessor");
+ parentPostProcessors.remove(beanPostProcessor);
+ }
+ }
+ }
+ catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+
+ List aggregatedPostProcessors = new ArrayList<>();
+ aggregatedPostProcessors.addAll(childPostProcessors);
+ aggregatedPostProcessors.addAll(parentPostProcessors);
+
+ for (BeanPostProcessor beanPostProcessor : new ArrayList<>(aggregatedPostProcessors)) {
+ for (Class> cls : beanPostProcessorExcludeClasses) {
+ if (cls.isAssignableFrom(beanPostProcessor.getClass())) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Removing bean post processor: " + beanPostProcessor + " of type " + cls);
}
+ aggregatedPostProcessors.remove(beanPostProcessor);
}
+ }
+ }
+
+ beanFactory.copyConfigurationFrom(parent);
+
+ List beanPostProcessors = beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory)
+ .getBeanPostProcessors() : new ArrayList<>();
+
+ beanPostProcessors.clear();
+ beanPostProcessors.addAll(aggregatedPostProcessors);
}
}
@Override
public String toString() {
- return "ApplicationContextFactory [resource=" + resource + "]";
+ return "ApplicationContextFactory [resources=" + Arrays.toString(resources) + "]";
}
@Override
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java
index 1f7506439e..af862552b0 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java
index 125e3daa9d..0efb7189ec 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -38,6 +38,7 @@ public class ApplicationContextJobFactory implements JobFactory {
* containing a job with the job name provided
*/
public ApplicationContextJobFactory(String jobName, ApplicationContextFactory applicationContextFactory) {
+ @SuppressWarnings("resource")
ConfigurableApplicationContext context = applicationContextFactory.createApplicationContext();
this.job = context.getBean(jobName, Job.class);
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java
index 293108b749..2c64127559 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -25,11 +25,9 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
import org.springframework.context.Lifecycle;
-import org.springframework.context.event.ContextClosedEvent;
-import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.SmartLifecycle;
+import org.springframework.context.event.ApplicationContextEvent;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@@ -40,13 +38,14 @@
*
* @author Lucas Ward
* @author Dave Syer
+ * @author Mahmoud Ben Hassine
*
* @since 2.1
*/
-public class AutomaticJobRegistrar implements Ordered, Lifecycle, ApplicationListener, ApplicationContextAware,
+public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, ApplicationContextAware,
InitializingBean {
- private Collection applicationContextFactories = new ArrayList();
+ private Collection applicationContextFactories = new ArrayList<>();
private JobLoader jobLoader;
@@ -54,13 +53,17 @@ public class AutomaticJobRegistrar implements Ordered, Lifecycle, ApplicationLis
private volatile boolean running = false;
+ private int phase = Integer.MIN_VALUE + 1000;
+
+ private boolean autoStartup = true;
+
private Object lifecycleMonitor = new Object();
private int order = Ordered.LOWEST_PRECEDENCE;
/**
- * The enclosing application context, which can be used to check if {@link ApplicationEvent events} come from the
- * expected source.
+ * The enclosing application context, which can be used to check if {@link ApplicationContextEvent events} come
+ * from the expected source.
*
* @param applicationContext the enclosing application context if there is one
* @see ApplicationContextAware#setApplicationContext(ApplicationContext)
@@ -125,25 +128,6 @@ public void afterPropertiesSet() {
}
- /**
- * Creates all the application contexts required and set up job registry entries with all the instances of
- * {@link Job} found therein. Also closes the contexts when the enclosing context is closed.
- *
- * @see InitializingBean#afterPropertiesSet()
- */
- @Override
- public final void onApplicationEvent(ApplicationEvent event) {
- // TODO: With Spring 3 a SmartLifecycle is started automatically
- if (event.getSource() == applicationContext) {
- if (event instanceof ContextRefreshedEvent) {
- start();
- }
- else if (event instanceof ContextClosedEvent) {
- stop();
- }
- }
- }
-
/**
* Delegates to {@link JobLoader#clear()}.
*
@@ -193,4 +177,36 @@ public boolean isRunning() {
}
}
+ @Override
+ public boolean isAutoStartup() {
+ return autoStartup;
+ }
+
+ /**
+ * @param autoStartup true for auto start.
+ * @see #isAutoStartup()
+ */
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ @Override
+ public int getPhase() {
+ return phase;
+ }
+
+ /**
+ * @param phase the phase.
+ * @see #getPhase()
+ */
+ public void setPhase(int phase) {
+ this.phase = phase;
+ }
+
+ @Override
+ public void stop(Runnable callback) {
+ stop();
+ callback.run();
+ }
+
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlApplicationContextFactory.java
index cda0ca50e9..1c60796dbe 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlApplicationContextFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlApplicationContextFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -29,6 +29,7 @@
*
* @deprecated use {@link GenericApplicationContextFactory} instead
*/
+@Deprecated
public class ClassPathXmlApplicationContextFactory extends GenericApplicationContextFactory {
/**
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
index 728c7a8f45..6e6befb601 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClassPathXmlJobRegistry.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2008-2010 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
+ *
+ * https://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.core.configuration.support;
/**
@@ -7,6 +22,7 @@
*
* @deprecated in version 2.1, please us {@link AutomaticJobRegistrar} instead
*/
+@Deprecated
public abstract class ClassPathXmlJobRegistry {
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java
index ba8b9d2630..b3cafa638e 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -19,7 +19,6 @@
import java.util.Arrays;
import java.util.List;
-import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -37,9 +36,9 @@
* @author Dave Syer
*
*/
-public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean, ApplicationContextAware {
+public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean, ApplicationContextAware {
- private List resources = new ArrayList();
+ private List resources = new ArrayList<>();
private boolean copyConfiguration = true;
@@ -57,7 +56,7 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean,
* resources can be given as a pattern (e.g.
* classpath*:/config/*-context.xml).
*
- * @param resources
+ * @param resources array of resources to use
*/
public void setResources(Resource[] resources) {
this.resources = Arrays.asList(resources);
@@ -105,17 +104,16 @@ public void setBeanPostProcessorExcludeClasses(Class>[] beanPostProcessorExclu
* in {@link #setResources(Resource[])}.
*
* @return an array of {@link ApplicationContextFactory}
- * @throws Exception
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
@Override
- public Object getObject() throws Exception {
+ public ApplicationContextFactory[] getObject() throws Exception {
if (resources == null) {
return new ApplicationContextFactory[0];
}
- List applicationContextFactories = new ArrayList();
+ List applicationContextFactories = new ArrayList<>();
for (Resource resource : resources) {
GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource);
factory.setCopyConfiguration(copyConfiguration);
@@ -158,7 +156,6 @@ public boolean isSingleton() {
* factories.
*
* @param applicationContext the {@link ApplicationContext} to set
- * @throws BeansException
* @see ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
@Override
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java
index cf3bc97db7..562c1f6be9 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -23,6 +23,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.DuplicateJobException;
@@ -34,6 +35,7 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -44,6 +46,7 @@
*
* @author Dave Syer
* @author Stephane Nicoll
+ * @author Mahmoud Ben Hassine
*/
public class DefaultJobLoader implements JobLoader, InitializingBean {
@@ -52,9 +55,9 @@ public class DefaultJobLoader implements JobLoader, InitializingBean {
private JobRegistry jobRegistry;
private StepRegistry stepRegistry;
- private Map contexts = new ConcurrentHashMap();
+ private Map contexts = new ConcurrentHashMap<>();
- private Map> contextToJobNames = new ConcurrentHashMap>();
+ private Map> contextToJobNames = new ConcurrentHashMap<>();
/**
* Default constructor useful for declarative configuration.
@@ -76,9 +79,9 @@ public DefaultJobLoader(JobRegistry jobRegistry) {
* Creates a job loader with the job and step registries provided.
*
* @param jobRegistry a {@link JobRegistry}
- * @param stepRegistry a {@link StepRegistry}
+ * @param stepRegistry a {@link StepRegistry} (can be {@code null})
*/
- public DefaultJobLoader(JobRegistry jobRegistry, StepRegistry stepRegistry) {
+ public DefaultJobLoader(JobRegistry jobRegistry, @Nullable StepRegistry stepRegistry) {
this.jobRegistry = jobRegistry;
this.stepRegistry = stepRegistry;
}
@@ -118,6 +121,7 @@ public void clear() {
doUnregister(jobName);
}
contexts.clear();
+ contextToJobNames.clear();
}
@Override
@@ -127,7 +131,9 @@ public Collection reload(ApplicationContextFactory factory) {
if (contexts.containsKey(factory)) {
ConfigurableApplicationContext context = contexts.get(factory);
for (String name : contextToJobNames.get(context)) {
- logger.debug("Unregistering job: " + name + " from context: " + context.getDisplayName());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Unregistering job: " + name + " from context: " + context.getDisplayName());
+ }
doUnregister(name);
}
context.close();
@@ -147,6 +153,7 @@ public Collection load(ApplicationContextFactory factory) throws DuplicateJ
return doLoad(factory, false);
}
+ @SuppressWarnings("resource")
private Collection doLoad(ApplicationContextFactory factory, boolean unregister) throws DuplicateJobException {
Collection jobNamesBefore = jobRegistry.getJobNames();
@@ -155,7 +162,7 @@ private Collection doLoad(ApplicationContextFactory factory, boolean unregi
// Try to detect auto-registration (e.g. through a bean post processor)
boolean autoRegistrationDetected = jobNamesAfter.size() > jobNamesBefore.size();
- Collection jobsRegistered = new HashSet();
+ Collection jobsRegistered = new HashSet<>();
if (autoRegistrationDetected) {
for (String name : jobNamesAfter) {
if (!jobNamesBefore.contains(name)) {
@@ -176,18 +183,22 @@ private Collection doLoad(ApplicationContextFactory factory, boolean unregi
// On reload try to unregister first
if (unregister) {
- logger.debug("Unregistering job: " + jobName + " from context: " + context.getDisplayName());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Unregistering job: " + jobName + " from context: " + context.getDisplayName());
+ }
doUnregister(jobName);
}
- logger.debug("Registering job: " + jobName + " from context: " + context.getDisplayName());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Registering job: " + jobName + " from context: " + context.getDisplayName());
+ }
doRegister(context, job);
jobsRegistered.add(jobName);
}
}
- Collection result = new ArrayList();
+ Collection result = new ArrayList<>();
for (String name : jobsRegistered) {
try {
result.add(jobRegistry.getJob(name));
@@ -207,7 +218,7 @@ private Collection doLoad(ApplicationContextFactory factory, boolean unregi
/**
* Returns all the {@link Step} instances defined by the specified {@link StepLocator}.
- *
+ *
* The specified jobApplicationContext is used to collect additional steps that
* are not exposed by the step locator
*
@@ -218,7 +229,7 @@ private Collection doLoad(ApplicationContextFactory factory, boolean unregi
*/
private Collection getSteps(final StepLocator stepLocator, final ApplicationContext jobApplicationContext) {
final Collection stepNames = stepLocator.getStepNames();
- final Collection result = new ArrayList();
+ final Collection result = new ArrayList<>();
for (String stepName : stepNames) {
result.add(stepLocator.getStep(stepName));
}
@@ -226,7 +237,6 @@ private Collection getSteps(final StepLocator stepLocator, final Applicati
// Because some steps are referenced by name, we need to look in the context to see if there
// are more Step instances defined. Right now they are registered as being available in the
// context of the job but we have no idea if they are linked to that Job or not.
- @SuppressWarnings("unchecked")
final Map allSteps = jobApplicationContext.getBeansOfType(Step.class);
for (Map.Entry entry : allSteps.entrySet()) {
if (!stepNames.contains(entry.getKey())) {
@@ -238,7 +248,7 @@ private Collection getSteps(final StepLocator stepLocator, final Applicati
/**
* Registers the specified {@link Job} defined in the specified {@link ConfigurableApplicationContext}.
- *
+ *
* Makes sure to update the {@link StepRegistry} if it is available.
*
* @param context the context in which the job is defined
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java
index 34e92ce864..4fd69ea6ad 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -16,8 +16,6 @@
package org.springframework.batch.core.configuration.support;
-import java.io.IOException;
-
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -28,6 +26,12 @@
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* {@link ApplicationContextFactory} implementation that takes a parent context and a path to the context to create.
@@ -41,30 +45,48 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext
/**
* Create an application context factory for the resource specified. The resource can be an actual {@link Resource},
* in which case it will be interpreted as an XML file, or it can be a @Configuration class, or a package name.
+ * All types must be the same (mixing XML with a java package for example is not allowed and will result in an
+ * {@link java.lang.IllegalArgumentException}).
*
- * @param resource a resource (XML configuration file, @Configuration class or java package to scan)
+ * @param resources some resources (XML configuration files, @Configuration classes or java packages to scan)
*/
- public GenericApplicationContextFactory(Object resource) {
- super(resource);
+ public GenericApplicationContextFactory(Object... resources) {
+ super(resources);
}
/**
- * @see AbstractApplicationContextFactory#createApplicationContext(ConfigurableApplicationContext, Object)
+ * @see AbstractApplicationContextFactory#createApplicationContext(ConfigurableApplicationContext, Object...)
*/
@Override
protected ConfigurableApplicationContext createApplicationContext(ConfigurableApplicationContext parent,
- Object resource) {
- if (resource instanceof Resource) {
- return new ResourceXmlApplicationContext(parent, (Resource) resource);
- }
- if (resource instanceof Class>) {
- return new ResourceAnnotationApplicationContext(parent, resource);
+ Object... resources) {
+ ConfigurableApplicationContext context;
+
+ if (allObjectsOfType(resources, Resource.class)) {
+ context = new ResourceXmlApplicationContext(parent, resources);
+ } else if (allObjectsOfType(resources, Class.class)) {
+ context = new ResourceAnnotationApplicationContext(parent, resources);
+ } else if (allObjectsOfType(resources, String.class)) {
+ context = new ResourceAnnotationApplicationContext(parent, resources);
+ } else {
+ List> types = new ArrayList<>();
+ for (Object resource : resources) {
+ types.add(resource.getClass());
+ }
+ throw new IllegalArgumentException("No application context could be created for resource types: "
+ + Arrays.toString(types.toArray()));
}
- if (resource instanceof String) {
- return new ResourceAnnotationApplicationContext(parent, resource);
+
+ return context;
+ }
+
+ private boolean allObjectsOfType(Object[] objects, Class> type) {
+ for (Object object : objects) {
+ if (!type.isInstance(object)) {
+ return false;
+ }
}
- throw new IllegalArgumentException("No application context could be created for resource type: "
- + resource.getClass());
+ return true;
}
private abstract class ApplicationContextHelper {
@@ -74,7 +96,7 @@ private abstract class ApplicationContextHelper {
private final ConfigurableApplicationContext parent;
public ApplicationContextHelper(ConfigurableApplicationContext parent, GenericApplicationContext context,
- Object config) {
+ Object... config) {
this.parent = parent;
if (parent != null) {
Assert.isTrue(parent.getBeanFactory() instanceof DefaultListableBeanFactory,
@@ -90,9 +112,9 @@ public ApplicationContextHelper(ConfigurableApplicationContext parent, GenericAp
prepareContext(parent, context);
}
- protected abstract String generateId(Object config);
+ protected abstract String generateId(Object... configs);
- protected abstract void loadConfiguration(Object config);
+ protected abstract void loadConfiguration(Object... configs);
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (parentBeanFactory != null) {
@@ -114,24 +136,35 @@ private final class ResourceXmlApplicationContext extends GenericXmlApplicationC
/**
* @param parent
*/
- public ResourceXmlApplicationContext(ConfigurableApplicationContext parent, Resource resource) {
- helper = new ApplicationContextHelper(parent, this, resource) {
+ public ResourceXmlApplicationContext(ConfigurableApplicationContext parent, Object... resources) {
+
+ class ResourceXmlApplicationContextHelper extends ApplicationContextHelper {
+
+ ResourceXmlApplicationContextHelper(ConfigurableApplicationContext parent, GenericApplicationContext context, Object... config) {
+ super(parent, context, config);
+ }
+
@Override
- protected String generateId(Object config) {
- Resource resource = (Resource) config;
- try {
- return resource.getURI().toString();
- }
- catch (IOException e) {
- return resource.toString();
- }
+ protected String generateId(Object... configs) {
+ Resource[] resources = Arrays.copyOfRange(configs, 0, configs.length, Resource[].class);
+ try {
+ List uris = new ArrayList<>();
+ for (Resource resource : resources) {
+ uris.add(resource.getURI().toString());
+ }
+ return StringUtils.collectionToCommaDelimitedString(uris);
+ }
+ catch (IOException e) {
+ return Arrays.toString(resources);
+ }
}
@Override
- protected void loadConfiguration(Object config) {
- Resource resource = (Resource) config;
- load(resource);
+ protected void loadConfiguration(Object... configs) {
+ Resource[] resources = Arrays.copyOfRange(configs, 0, configs.length, Resource[].class);
+ load(resources);
}
- };
+ }
+ helper = new ResourceXmlApplicationContextHelper(parent, this, resources);
refresh();
}
@@ -152,30 +185,41 @@ private final class ResourceAnnotationApplicationContext extends AnnotationConfi
private final ApplicationContextHelper helper;
- public ResourceAnnotationApplicationContext(ConfigurableApplicationContext parent, Object resource) {
- helper = new ApplicationContextHelper(parent, this, resource) {
+ public ResourceAnnotationApplicationContext(ConfigurableApplicationContext parent, Object... resources) {
+
+ class ResourceAnnotationApplicationContextHelper extends ApplicationContextHelper {
+
+ public ResourceAnnotationApplicationContextHelper(ConfigurableApplicationContext parent, GenericApplicationContext context, Object... config) {
+ super(parent, context, config);
+ }
+
@Override
- protected String generateId(Object config) {
- if (config instanceof Class) {
- Class> type = (Class>) config;
- return type.getName();
+ protected String generateId(Object... configs) {
+ if (allObjectsOfType(configs, Class.class)) {
+ Class>[] types = Arrays.copyOfRange(configs, 0, configs.length, Class[].class);
+ List names = new ArrayList<>();
+ for (Class> type : types) {
+ names.add(type.getName());
+ }
+ return StringUtils.collectionToCommaDelimitedString(names);
}
else {
- return config.toString();
+ return Arrays.toString(configs);
}
}
@Override
- protected void loadConfiguration(Object config) {
- if (config instanceof Class) {
- Class> type = (Class>) config;
- register(type);
+ protected void loadConfiguration(Object... configs) {
+ if (allObjectsOfType(configs, Class.class)) {
+ Class>[] types = Arrays.copyOfRange(configs, 0, configs.length, Class[].class);
+ register(types);
}
else {
- String pkg = (String) config;
- scan(pkg);
+ String[] pkgs = Arrays.copyOfRange(configs, 0, configs.length, String[].class);
+ scan(pkgs);
}
}
- };
+ }
+ helper = new ResourceAnnotationApplicationContextHelper(parent, this, resources);
refresh();
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java
index be40fc9859..3ceb7e157c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2018 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
+ * https://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,
@@ -19,6 +19,7 @@
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersIncrementer;
import org.springframework.batch.core.JobParametersValidator;
+import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -28,10 +29,11 @@
* financeDepartment, which would result in a {@link Job} with
* identical functionality but named financeDepartment.overnightJob
* . The use of a "." separator for elements is deliberate, since it is a "safe"
- * character in a URL.
+ * character in a URL.
*
*
* @author Dave Syer
+ * @author Mahmoud Ben Hassine
*
*/
public class GroupAwareJob implements Job {
@@ -58,10 +60,10 @@ public GroupAwareJob(Job delegate) {
/**
* Create a new {@link Job} with the given group name and delegate.
*
- * @param groupName the group name to prepend
+ * @param groupName the group name to prepend (can be {@code null})
* @param delegate a delegate for the features of a regular Job
*/
- public GroupAwareJob(String groupName, Job delegate) {
+ public GroupAwareJob(@Nullable String groupName, Job delegate) {
super();
this.groupName = groupName;
this.delegate = delegate;
@@ -89,6 +91,7 @@ public boolean isRestartable() {
}
@Override
+ @Nullable
public JobParametersIncrementer getJobParametersIncrementer() {
return delegate.getJobParametersIncrementer();
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java
index 1521a15afd..db246f5dfa 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java
index 7352ed7027..b997e62378 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java
index 643e9c439c..4eb2a26251 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -52,7 +52,7 @@ public class JobRegistryBeanPostProcessor implements BeanPostProcessor, BeanFact
// It doesn't make sense for this to have a default value...
private JobRegistry jobRegistry = null;
- private Collection jobNames = new HashSet();
+ private Collection jobNames = new HashSet<>();
private String groupName = null;
@@ -106,14 +106,16 @@ public void afterPropertiesSet() throws Exception {
}
/**
- * De-register all the {@link Job} instances that were regsistered by this
+ * Unregister all the {@link Job} instances that were registered by this
* post processor.
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
@Override
public void destroy() throws Exception {
for (String name : jobNames) {
- logger.debug("Unregistering job: " + name);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Unregistering job: " + name);
+ }
jobRegistry.unregister(name);
}
jobNames.clear();
@@ -138,7 +140,9 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
job = groupName==null ? job : new GroupAwareJob(groupName, job);
ReferenceJobFactory jobFactory = new ReferenceJobFactory(job);
String name = jobFactory.getJobName();
- logger.debug("Registering job: " + name);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Registering job: " + name);
+ }
jobRegistry.register(jobFactory);
jobNames.add(name);
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java
index 9cd93cb541..590aaa463a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2019 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
+ * https://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,
@@ -25,6 +25,7 @@
import org.springframework.batch.core.configuration.JobFactory;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -32,6 +33,7 @@
*
* @author Dave Syer
* @author Robert Fischer
+ * @author Mahmoud Ben Hassine
*/
public class MapJobRegistry implements JobRegistry {
@@ -39,11 +41,11 @@ public class MapJobRegistry implements JobRegistry {
* The map holding the registered job factories.
*/
// The "final" ensures that it is visible and initialized when the constructor resolves.
- private final ConcurrentMap map = new ConcurrentHashMap();
+ private final ConcurrentMap map = new ConcurrentHashMap<>();
@Override
public void register(JobFactory jobFactory) throws DuplicateJobException {
- Assert.notNull(jobFactory);
+ Assert.notNull(jobFactory, "jobFactory is null");
String name = jobFactory.getJobName();
Assert.notNull(name, "Job configuration must have a name.");
JobFactory previousValue = map.putIfAbsent(name, jobFactory);
@@ -60,7 +62,7 @@ public void unregister(String name) {
}
@Override
- public Job getJob(String name) throws NoSuchJobException {
+ public Job getJob(@Nullable String name) throws NoSuchJobException {
JobFactory factory = map.get(name);
if (factory == null) {
throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered");
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java
index fea8816e7b..b54e4ca507 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -37,7 +37,7 @@
*/
public class MapStepRegistry implements StepRegistry {
- private final ConcurrentMap> map = new ConcurrentHashMap>();
+ private final ConcurrentMap> map = new ConcurrentHashMap<>();
@Override
public void register(String jobName, Collection steps) throws DuplicateJobException {
@@ -45,7 +45,7 @@ public void register(String jobName, Collection steps) throws DuplicateJob
Assert.notNull(steps, "The job steps cannot be null.");
- final Map jobSteps = new HashMap();
+ final Map jobSteps = new HashMap<>();
for (Step step : steps) {
jobSteps.put(step.getName(), step);
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/OsgiBundleXmlApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/OsgiBundleXmlApplicationContextFactory.java
deleted file mode 100644
index 82c2942faf..0000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/OsgiBundleXmlApplicationContextFactory.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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 org.springframework.batch.core.configuration.support;
-
-import org.osgi.framework.BundleContext;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.osgi.context.BundleContextAware;
-import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext;
-
-/**
- * {@link ApplicationContextFactory} that can be used to load a context from an
- * XML location in a bundle.
- *
- * @author Dave Syer
- *
- */
-public class OsgiBundleXmlApplicationContextFactory implements BundleContextAware, ApplicationContextFactory,
-ApplicationContextAware {
-
- private BundleContext bundleContext;
-
- private ApplicationContext parent;
-
- private String path;
-
- private String displayName;
-
- /**
- * @param path the resource path to the xml to load for the child context.
- */
- public void setPath(String path) {
- this.path = path;
- }
-
- /**
- * @param displayName the display name for the application context created.
- */
- public void setDisplayName(String displayName) {
- this.displayName = displayName;
- }
-
- /**
- * Setter for the parent application context.
- *
- * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
- */
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- parent = applicationContext;
- }
-
- /**
- * Stash the {@link BundleContext} for creating a job application context
- * later.
- *
- * @see org.springframework.osgi.context.BundleContextAware#setBundleContext(org.osgi.framework.BundleContext)
- */
- @Override
- public void setBundleContext(BundleContext context) {
- this.bundleContext = context;
- }
-
- /**
- * Create an application context from the provided path, using the current
- * OSGi {@link BundleContext} and the enclosing Spring
- * {@link ApplicationContext} as a parent context.
- *
- * @see ApplicationContextFactory#createApplicationContext()
- */
- @Override
- public ConfigurableApplicationContext createApplicationContext() {
- OsgiBundleXmlApplicationContext context = new OsgiBundleXmlApplicationContext(new String[] { path }, parent);
- String displayName = bundleContext.getBundle().getSymbolicName() + ":" + this.displayName;
- context.setDisplayName(displayName);
- context.setBundleContext(bundleContext);
- context.refresh();
- return context;
- }
-
- @Override
- public String toString() {
- String bundleId = bundleContext == null ? null : (bundleContext.getBundle() == null ? bundleContext.toString()
- : "" + bundleContext.getBundle().getBundleId());
- return "OsgiBundleXmlApplicationContext [path=" + path + ", bundle=" + bundleId + "]";
- }
-
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- return toString().equals(obj.toString());
- }
-
-}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java
index 0427aebe3e..7d8ab4fc05 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package-info.java
new file mode 100644
index 0000000000..ba3ed75998
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Specific implementations of configuration concerns.
+ *
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ */
+@NonNullApi
+package org.springframework.batch.core.configuration.support;
+
+import org.springframework.lang.NonNullApi;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package.html b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package.html
deleted file mode 100644
index f0c19561d4..0000000000
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-Specific implementations of configuration concerns.
-
-
-
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
index 9f91af2f16..5b4c3e3d26 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2008 the original author or authors.
+ * Copyright 2006-2014 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
+ * https://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,
@@ -18,12 +18,16 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
@@ -33,43 +37,42 @@
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
/**
* @author Dave Syer
- *
+ * @author Michael Minella
+ * @author Chris Schaefer
+ *
*/
public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionParser {
- private static final String ID_ATTR = "id";
+ protected static final String ID_ATTR = "id";
- private static final String STEP_ELE = "step";
+ protected static final String STEP_ELE = "step";
- private static final String FLOW_ELE = "flow";
+ protected static final String FLOW_ELE = "flow";
- private static final String DECISION_ELE = "decision";
+ protected static final String DECISION_ELE = "decision";
- private static final String SPLIT_ELE = "split";
+ protected static final String SPLIT_ELE = "split";
- private static final String NEXT_ATTR = "next";
+ protected static final String NEXT_ATTR = "next";
- private static final String NEXT_ELE = "next";
+ protected static final String NEXT_ELE = "next";
- private static final String END_ELE = "end";
+ protected static final String END_ELE = "end";
- private static final String FAIL_ELE = "fail";
+ protected static final String FAIL_ELE = "fail";
- private static final String STOP_ELE = "stop";
+ protected static final String STOP_ELE = "stop";
- private static final String ON_ATTR = "on";
+ protected static final String ON_ATTR = "on";
- private static final String TO_ATTR = "to";
+ protected static final String TO_ATTR = "to";
- private static final String RESTART_ATTR = "restart";
+ protected static final String RESTART_ATTR = "restart";
- private static final String EXIT_CODE_ATTR = "exit-code";
+ protected static final String EXIT_CODE_ATTR = "exit-code";
private static final InlineStepParser stepParser = new InlineStepParser();
@@ -78,7 +81,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
private static final DecisionParser decisionParser = new DecisionParser();
// For generating unique state names for end transitions
- private static int endCounter = 0;
+ protected static int endCounter = 0;
private String jobFactoryRef;
@@ -86,8 +89,8 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
* Convenience method for subclasses to set the job factory reference if it
* is available (null is fine, but the quality of error reports is better if
* it is available).
- *
- * @param jobFactoryRef
+ *
+ * @param jobFactoryRef name of the ref
*/
protected void setJobFactoryRef(String jobFactoryRef) {
this.jobFactoryRef = jobFactoryRef;
@@ -95,7 +98,7 @@ protected void setJobFactoryRef(String jobFactoryRef) {
/*
* (non-Javadoc)
- *
+ *
* @see AbstractSingleBeanDefinitionParser#getBeanClass(Element)
*/
@Override
@@ -110,7 +113,7 @@ protected Class> getBeanClass(Element element) {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
- List stateTransitions = new ArrayList();
+ List stateTransitions = new ArrayList<>();
SplitParser splitParser = new SplitParser(jobFactoryRef);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
@@ -118,7 +121,7 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit
parserContext.pushContainingComponent(compositeDef);
boolean stepExists = false;
- Map> reachableElementMap = new HashMap>();
+ Map> reachableElementMap = new LinkedHashMap<>();
String startElement = null;
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
@@ -160,7 +163,7 @@ else if (nodeName.equals(SPLIT_ELE)) {
}
// Ensure that all elements are reachable
- Set allReachableElements = new HashSet();
+ Set allReachableElements = new HashSet<>();
findAllReachableElements(startElement, reachableElementMap, allReachableElements);
for (String elementId : reachableElementMap.keySet()) {
if (!allReachableElements.contains(elementId)) {
@@ -168,21 +171,20 @@ else if (nodeName.equals(SPLIT_ELE)) {
}
}
- ManagedList managedList = new ManagedList();
- @SuppressWarnings( { "unchecked", "unused" })
- boolean dummy = managedList.addAll(stateTransitions);
+ ManagedList managedList = new ManagedList<>();
+ managedList.addAll(stateTransitions);
builder.addPropertyValue("stateTransitions", managedList);
}
/**
* Find all of the elements that are pointed to by this element.
- *
- * @param element
+ *
+ * @param element The parent element
* @return a collection of reachable element names
*/
private Set findReachableElements(Element element) {
- Set reachableElements = new HashSet();
+ Set reachableElements = new HashSet<>();
String nextAttribute = element.getAttribute(NEXT_ATTR);
if (StringUtils.hasText(nextAttribute)) {
@@ -206,12 +208,12 @@ private Set findReachableElements(Element element) {
/**
* Find all of the elements reachable from the startElement.
- *
- * @param startElement
- * @param reachableElementMap
+ *
+ * @param startElement name of the element to start from
+ * @param reachableElementMap Map of elements that can be reached from the startElement
* @param accumulator a collection of reachable element names
*/
- private void findAllReachableElements(String startElement, Map> reachableElementMap,
+ protected void findAllReachableElements(String startElement, Map> reachableElementMap,
Set accumulator) {
Set reachableIds = reachableElementMap.get(startElement);
accumulator.add(startElement);
@@ -233,7 +235,7 @@ private void findAllReachableElements(String startElement, Map getNextElements(ParserContext parserContext, BeanDefinition stateDef,
+ public static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef,
Element element) {
return getNextElements(parserContext, null, stateDef, element);
}
@@ -248,10 +250,10 @@ protected static Collection getNextElements(ParserContext parser
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
- protected static Collection getNextElements(ParserContext parserContext, String stepId,
+ public static Collection getNextElements(ParserContext parserContext, String stepId,
BeanDefinition stateDef, Element element) {
- Collection list = new ArrayList();
+ Collection list = new ArrayList<>();
String shortNextAttribute = element.getAttribute(NEXT_ATTR);
boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute);
@@ -260,7 +262,7 @@ protected static Collection getNextElements(ParserContext parser
}
boolean transitionElementExists = false;
- List patterns = new ArrayList();
+ List patterns = new ArrayList<>();
for (String transitionName : new String[] { NEXT_ELE, STOP_ELE, END_ELE, FAIL_ELE }) {
List transitionElements = DomUtils.getChildElementsByTagName(element, transitionName);
for (Element transitionElement : transitionElements) {
@@ -283,7 +285,7 @@ protected static Collection getNextElements(ParserContext parser
else if (hasNextAttribute) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> may not contain a '" + NEXT_ATTR
- + "' attribute and a transition element", element);
+ + "' attribute and a transition element", element);
}
return list;
@@ -292,10 +294,10 @@ else if (hasNextAttribute) {
/**
* @param transitionElement The element to parse
* @param patterns a list of patterns on state transitions for this element
- * @param element
+ * @param element {@link Element} representing the source.
* @param parserContext the parser context for the bean factory
*/
- private static void verifyUniquePattern(Element transitionElement, List patterns, Element element,
+ protected static void verifyUniquePattern(Element transitionElement, List patterns, Element element,
ParserContext parserContext) {
String onAttribute = transitionElement.getAttribute(ON_ATTR);
if (patterns.contains(onAttribute)) {
@@ -309,7 +311,7 @@ private static void verifyUniquePattern(Element transitionElement, List
* @param transitionElement The element to parse
* @param stateDef The bean definition for the current state
* @param parserContext the parser context for the bean factory
- * @param a collection of
+ * @return a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
@@ -340,11 +342,12 @@ private static Collection parseTransitionElement(Element transit
* default to batchStatus.
* @param stateDef The bean definition for the current state
* @param parserContext the parser context for the bean factory
- * @param a collection of
+ * @param abandon the abandon flag to be used by the transition.
+ * @return a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
- private static Collection createTransition(FlowExecutionStatus status, String on, String next,
+ protected static Collection createTransition(FlowExecutionStatus status, String on, String next,
String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) {
BeanDefinition endState = null;
@@ -373,7 +376,7 @@ private static Collection createTransition(FlowExecutionStatus s
}
- Collection list = new ArrayList();
+ Collection list = new ArrayList<>();
list.add(getStateTransitionReference(parserContext, stateDef, on, next));
if (endState != null) {
//
@@ -389,8 +392,8 @@ private static Collection createTransition(FlowExecutionStatus s
* @param elementName An end transition element name
* @return the BatchStatus corresponding to the transition name
*/
- private static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) {
- elementName = stripNamespace(elementName);
+ protected static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) {
+ elementName = stripNamespace(elementName);
if (STOP_ELE.equals(elementName)) {
return FlowExecutionStatus.STOPPED;
}
@@ -405,17 +408,17 @@ else if (FAIL_ELE.equals(elementName)) {
}
}
- /**
- * Strip the namespace from the element name if it exists.
- */
- private static String stripNamespace(String elementName){
- if(elementName.startsWith("batch:")){
- return elementName.substring(6);
- }
- else{
- return elementName;
- }
- }
+ /**
+ * Strip the namespace from the element name if it exists.
+ */
+ private static String stripNamespace(String elementName){
+ if(elementName.startsWith("batch:")){
+ return elementName.substring(6);
+ }
+ else{
+ return elementName;
+ }
+ }
/**
* @param parserContext the parser context
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java
index 870195a492..6331381cc1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2009-2014 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
+ *
+ * https://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.core.configuration.xml;
import java.util.ArrayList;
@@ -39,11 +54,10 @@ public AbstractBeanDefinition parse(Element element, ParserContext parserContext
return builder.getBeanDefinition();
}
- @SuppressWarnings("unchecked")
public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
builder.addPropertyValue("delegate", parseListenerElement(element, parserContext, builder.getRawBeanDefinition()));
- ManagedMap metaDataMap = new ManagedMap();
+ ManagedMap metaDataMap = new ManagedMap<>();
for (String metaDataPropertyName : getMethodNameAttributes()) {
String listenerMethod = element.getAttribute(metaDataPropertyName);
if (StringUtils.hasText(listenerMethod)) {
@@ -53,7 +67,6 @@ public void doParse(Element element, ParserContext parserContext, BeanDefinition
builder.addPropertyValue("metaDataMap", metaDataMap);
}
- @SuppressWarnings("unchecked")
public static BeanMetadataElement parseListenerElement(Element element, ParserContext parserContext, BeanDefinition enclosing) {
String listenerRef = element.getAttribute(REF_ATTR);
List beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE);
@@ -112,14 +125,14 @@ else if (refElements.size() > 1) {
}
private List getMethodNameAttributes() {
- List methodNameAttributes = new ArrayList();
+ List methodNameAttributes = new ArrayList<>();
for (ListenerMetaData metaData : getMetaDataValues()) {
methodNameAttributes.add(metaData.getPropertyName());
}
return methodNameAttributes;
}
- protected abstract Class extends AbstractListenerFactoryBean> getBeanClass();
+ protected abstract Class extends AbstractListenerFactoryBean>> getBeanClass();
protected abstract ListenerMetaData[] getMetaDataValues();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java
index 8d33cb0b1e..4c5527698e 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -15,6 +15,10 @@
*/
package org.springframework.batch.core.configuration.xml;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
import org.springframework.batch.core.listener.StepListenerMetaData;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -28,9 +32,6 @@
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
/**
* Internal parser for the <step/> elements inside a job. A step element
@@ -89,9 +90,10 @@ public abstract class AbstractStepParser {
/**
* @param stepElement The <step/> element
- * @param parserContext
+ * @param parserContext instance of {@link ParserContext}.
* @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean}
* from the enclosing tag. Use 'null' if unknown.
+ * @return {@link AbstractBeanDefinition} for the stepElement.
*/
protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
index b864f253f5..33efd79037 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
index f9b2ef44b1..ff9327cde9 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -15,9 +15,13 @@
*/
package org.springframework.batch.core.configuration.xml;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
import org.springframework.batch.core.listener.StepListenerMetaData;
-import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
+import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -30,11 +34,9 @@
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
-import org.w3c.dom.Element;
-
-import java.util.List;
/**
* Internal parser for the <chunk/> element inside a step.
@@ -66,8 +68,11 @@ public class ChunkElementParser {
StepListenerMetaData.itemListenerMetaData());
/**
- * @param element
- * @param parserContext
+ * @param bd {@link AbstractBeanDefinition} instance of the containing bean.
+ * @param element the element to parse
+ * @param parserContext the context to use
+ * @param underspecified if true, a fatal error will not be raised if attribute
+ * or element is missing.
*/
protected void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, boolean underspecified) {
@@ -108,26 +113,33 @@ protected void parse(Element element, AbstractBeanDefinition bd, ParserContext p
if (propertyValues.contains("commitInterval")) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
- + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
+ + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
}
else {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
- + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element);
+ + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element);
}
}
String skipLimit = element.getAttribute("skip-limit");
- ManagedMap skippableExceptions = handleExceptionElement(element, parserContext, "skippable-exception-classes");
+ ManagedMap skippableExceptions =
+ new ExceptionElementParser().parse(element, parserContext, "skippable-exception-classes");
if (StringUtils.hasText(skipLimit)) {
if (skippableExceptions == null) {
- skippableExceptions = new ManagedMap();
+ skippableExceptions = new ManagedMap<>();
skippableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("skipLimit", skipLimit);
}
if (skippableExceptions != null) {
+ List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "skippable-exception-classes");
+
+ if(!CollectionUtils.isEmpty(exceptionClassElements)) {
+ skippableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR)
+ && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR)));
+ }
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("skippableExceptionClasses", skippableExceptions);
@@ -137,15 +149,22 @@ protected void parse(Element element, AbstractBeanDefinition bd, ParserContext p
underspecified);
String retryLimit = element.getAttribute("retry-limit");
- ManagedMap retryableExceptions = handleExceptionElement(element, parserContext, "retryable-exception-classes");
+ ManagedMap retryableExceptions =
+ new ExceptionElementParser().parse(element, parserContext, "retryable-exception-classes");
if (StringUtils.hasText(retryLimit)) {
if (retryableExceptions == null) {
- retryableExceptions = new ManagedMap();
+ retryableExceptions = new ManagedMap<>();
retryableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("retryLimit", retryLimit);
}
if (retryableExceptions != null) {
+ List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "retryable-exception-classes");
+
+ if(!CollectionUtils.isEmpty(exceptionClassElements)) {
+ retryableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR)
+ && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR)));
+ }
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("retryableExceptionClasses", retryableExceptions);
@@ -183,13 +202,12 @@ protected void parse(Element element, AbstractBeanDefinition bd, ParserContext p
private void handleItemHandler(AbstractBeanDefinition enclosing, String handlerName, String propertyName, String adapterClassName, boolean required,
Element element, ParserContext parserContext, MutablePropertyValues propertyValues, boolean underspecified) {
String refName = element.getAttribute(handlerName);
- @SuppressWarnings("unchecked")
List children = DomUtils.getChildElementsByTagName(element, handlerName);
if (children.size() == 1) {
if (StringUtils.hasText(refName)) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element may not have both a '" + handlerName
- + "' attribute and a <" + handlerName + "/> element.", element);
+ + "' attribute and a <" + handlerName + "/> element.", element);
}
handleItemHandlerElement(enclosing, propertyName, adapterClassName, propertyValues, children.get(0), parserContext);
}
@@ -204,7 +222,7 @@ else if (StringUtils.hasText(refName)) {
else if (required && !underspecified) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element has neither a '" + handlerName
- + "' attribute nor a <" + handlerName + "/> element.", element);
+ + "' attribute nor a <" + handlerName + "/> element.", element);
}
}
@@ -212,7 +230,6 @@ else if (required && !underspecified) {
* Handle the <reader/>, <processor/>, or <writer/> that
* is defined within the item handler.
*/
- @SuppressWarnings("unchecked")
private void handleItemHandlerElement(AbstractBeanDefinition enclosing, String propertyName, String adapterClassName,
MutablePropertyValues propertyValues, Element element, ParserContext parserContext) {
List beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE);
@@ -220,7 +237,7 @@ private void handleItemHandlerElement(AbstractBeanDefinition enclosing, String p
if (beanElements.size() + refElements.size() != 1) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> must have exactly one of either a <" + BEAN_ELE
- + "/> element or a <" + REF_ELE + "/> element.", element);
+ + "/> element or a <" + REF_ELE + "/> element.", element);
}
else if (beanElements.size() == 1) {
Element beanElement = beanElements.get(0);
@@ -270,7 +287,7 @@ private void handleRetryListenersElement(Element element, MutablePropertyValues
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(),
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
- ManagedList retryListenerBeans = new ManagedList();
+ ManagedList retryListenerBeans = new ManagedList<>();
retryListenerBeans.setMergeEnabled(listenersElement.hasAttribute(MERGE_ATTR)
&& Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR)));
handleRetryListenerElements(parserContext, listenersElement, retryListenerBeans, enclosing);
@@ -279,8 +296,7 @@ private void handleRetryListenersElement(Element element, MutablePropertyValues
}
}
- @SuppressWarnings("unchecked")
- private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans,
+ private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans,
BeanDefinition enclosing) {
List listenerElements = DomUtils.getChildElementsByTagName(element, "listener");
if (listenerElements != null) {
@@ -290,11 +306,10 @@ private void handleRetryListenerElements(ParserContext parserContext, Element el
}
}
- @SuppressWarnings("unchecked")
private void handleStreamsElement(Element element, MutablePropertyValues propertyValues, ParserContext parserContext) {
Element streamsElement = DomUtils.getChildElementByTagName(element, "streams");
if (streamsElement != null) {
- ManagedList streamBeans = new ManagedList();
+ ManagedList streamBeans = new ManagedList<>();
streamBeans.setMergeEnabled(streamsElement.hasAttribute(MERGE_ATTR)
&& Boolean.valueOf(streamsElement.getAttribute(MERGE_ATTR)));
List streamElements = DomUtils.getChildElementsByTagName(streamsElement, "stream");
@@ -314,34 +329,4 @@ private void handleStreamsElement(Element element, MutablePropertyValues propert
}
}
- @SuppressWarnings("unchecked")
- private ManagedMap handleExceptionElement(Element element, ParserContext parserContext, String exceptionListName) {
- List children = DomUtils.getChildElementsByTagName(element, exceptionListName);
- if (children.size() == 1) {
- ManagedMap map = new ManagedMap();
- Element exceptionClassesElement = children.get(0);
- map.setMergeEnabled(exceptionClassesElement.hasAttribute(MERGE_ATTR)
- && Boolean.valueOf(exceptionClassesElement.getAttribute(MERGE_ATTR)));
- addExceptionClasses("include", true, exceptionClassesElement, map, parserContext);
- addExceptionClasses("exclude", false, exceptionClassesElement, map, parserContext);
- map.put(ForceRollbackForWriteSkipException.class, true);
- return map;
- }
- else if (children.size() > 1) {
- parserContext.getReaderContext().error(
- "The <" + exceptionListName + "/> element may not appear more than once in a single <"
- + element.getNodeName() + "/>.", element);
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- private void addExceptionClasses(String elementName, boolean include, Element exceptionClassesElement,
- ManagedMap map, ParserContext parserContext) {
- for (Element child : (List) DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) {
- String className = child.getAttribute("class");
- map.put(new TypedStringValue(className, Class.class), include);
- }
- }
-
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
index 53890ac24c..5c461f9a27 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
index e7223c8fae..d8c71d9026 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -126,8 +126,7 @@ private Object injectDefaults(Object bean) {
if (jobRepository == null) {
fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME));
}
- }
- else if (bean instanceof StepParserStepFactoryBean) {
+ } else if (bean instanceof StepParserStepFactoryBean) {
StepParserStepFactoryBean, ?> fb = (StepParserStepFactoryBean, ?>) bean;
JobRepository jobRepository = fb.getJobRepository();
if (jobRepository == null) {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
index 426b038ba6..c72bec0d57 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2009 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.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -15,8 +15,8 @@
*/
package org.springframework.batch.core.configuration.xml;
-import java.util.Map;
-
+import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator;
+import org.springframework.batch.core.job.flow.support.StateTransition;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.TypedStringValue;
@@ -28,16 +28,26 @@
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
+import java.util.Comparator;
+import java.util.Map;
+
/**
* Utility methods used in parsing of the batch core namespace
*
* @author Thomas Risberg
+ * @author Michael Minella
*/
public class CoreNamespaceUtils {
private static final String STEP_SCOPE_PROCESSOR_BEAN_NAME = "org.springframework.batch.core.scope.internalStepScope";
- private static final String STEP_SCOPE_PROCESSOR_CLASS_NAME = "org.springframework.batch.core.scope.StepScope";
+ private static final String XML_CONFIG_STEP_SCOPE_PROCESSOR_CLASS_NAME = "org.springframework.batch.core.scope.StepScope";
+
+ private static final String JAVA_CONFIG_SCOPE_CLASS_NAME = "org.springframework.batch.core.configuration.annotation.ScopeConfiguration";
+
+ private static final String JOB_SCOPE_PROCESSOR_BEAN_NAME = "org.springframework.batch.core.scope.internalJobScope";
+
+ private static final String JOB_SCOPE_PROCESSOR_CLASS_NAME = "org.springframework.batch.core.scope.JobScope";
private static final String CUSTOM_EDITOR_CONFIGURER_CLASS_NAME = "org.springframework.beans.factory.config.CustomEditorConfigurer";
@@ -47,45 +57,73 @@ public class CoreNamespaceUtils {
private static final String CORE_NAMESPACE_POST_PROCESSOR_CLASS_NAME = "org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor";
- protected static void autoregisterBeansForNamespace(ParserContext parserContext, Object source) {
+ public static void autoregisterBeansForNamespace(ParserContext parserContext, Object source) {
checkForStepScope(parserContext, source);
+ checkForJobScope(parserContext, source);
addRangePropertyEditor(parserContext);
addCoreNamespacePostProcessor(parserContext);
+ addStateTransitionComparator(parserContext);
}
private static void checkForStepScope(ParserContext parserContext, Object source) {
- boolean foundStepScope = false;
+ checkForScope(parserContext, source, XML_CONFIG_STEP_SCOPE_PROCESSOR_CLASS_NAME, STEP_SCOPE_PROCESSOR_BEAN_NAME);
+ }
+
+ private static void checkForJobScope(ParserContext parserContext, Object source) {
+ checkForScope(parserContext, source, JOB_SCOPE_PROCESSOR_CLASS_NAME, JOB_SCOPE_PROCESSOR_BEAN_NAME);
+ }
+
+ private static void checkForScope(ParserContext parserContext, Object source, String scopeClassName,
+ String scopeBeanName) {
+ boolean foundScope = false;
String[] beanNames = parserContext.getRegistry().getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = parserContext.getRegistry().getBeanDefinition(beanName);
- if (STEP_SCOPE_PROCESSOR_CLASS_NAME.equals(bd.getBeanClassName())) {
- foundStepScope = true;
+ if (scopeClassName.equals(bd.getBeanClassName()) || JAVA_CONFIG_SCOPE_CLASS_NAME.equals(bd.getBeanClassName())) {
+ foundScope = true;
break;
}
}
- if (!foundStepScope) {
+ if (!foundScope) {
BeanDefinitionBuilder stepScopeBuilder = BeanDefinitionBuilder
- .genericBeanDefinition(STEP_SCOPE_PROCESSOR_CLASS_NAME);
+ .genericBeanDefinition(scopeClassName);
AbstractBeanDefinition abd = stepScopeBuilder.getBeanDefinition();
abd.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
abd.setSource(source);
- parserContext.getRegistry().registerBeanDefinition(STEP_SCOPE_PROCESSOR_BEAN_NAME, abd);
+ parserContext.getRegistry().registerBeanDefinition(scopeBeanName, abd);
}
}
+ /**
+ * Register a {@link Comparator} to be used to sort {@link StateTransition}s
+ *
+ * @param parserContext
+ */
+ private static void addStateTransitionComparator(ParserContext parserContext) {
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+ if (!stateTransitionComparatorAlreadyDefined(registry)) {
+ AbstractBeanDefinition defaultStateTransitionComparator = BeanDefinitionBuilder.genericBeanDefinition(
+ DefaultStateTransitionComparator.class).getBeanDefinition();
+ registry.registerBeanDefinition(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR, defaultStateTransitionComparator);
+ }
+ }
+
+ private static boolean stateTransitionComparatorAlreadyDefined(BeanDefinitionRegistry registry) {
+ return registry.containsBeanDefinition(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR);
+ }
+
/**
* Register a RangePropertyEditor if one does not already exist.
*
* @param parserContext
*/
- @SuppressWarnings("unchecked")
private static void addRangePropertyEditor(ParserContext parserContext) {
BeanDefinitionRegistry registry = parserContext.getRegistry();
if (!rangeArrayEditorAlreadyDefined(registry)) {
AbstractBeanDefinition customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(
CUSTOM_EDITOR_CONFIGURER_CLASS_NAME).getBeanDefinition();
customEditorConfigurer.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- ManagedMap editors = new ManagedMap();
+ ManagedMap editors = new ManagedMap<>();
editors.put(RANGE_ARRAY_CLASS_NAME, RANGE_ARRAY_EDITOR_CLASS_NAME);
customEditorConfigurer.getPropertyValues().addPropertyValue("customEditors", editors);
registry.registerBeanDefinition(CUSTOM_EDITOR_CONFIGURER_CLASS_NAME, customEditorConfigurer);
@@ -143,7 +181,7 @@ private static boolean coreNamespaceBeanPostProcessorAlreadyDefined(BeanDefiniti
* Should this element be treated as incomplete? If it has a parent or is
* abstract, then it may not have all properties.
*
- * @param element
+ * @param element to be evaluated.
* @return TRUE if the element is abstract or has a parent
*/
public static boolean isUnderspecified(Element element) {
@@ -151,7 +189,7 @@ public static boolean isUnderspecified(Element element) {
}
/**
- * @param element
+ * @param element to be evaluated.
* @return TRUE if the element is abstract
*/
public static boolean isAbstract(Element element) {
@@ -176,7 +214,8 @@ public static boolean namespaceMatchesVersion(Element element) {
private static boolean matchesVersionInternal(Element element) {
String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
- return schemaLocation.matches("(?m).*spring-batch-2.2.xsd.*")
+ return schemaLocation.matches("(?m).*spring-batch-3.0.xsd.*")
+ || schemaLocation.matches("(?m).*spring-batch-2.2.xsd.*")
|| schemaLocation.matches("(?m).*spring-batch.xsd.*")
|| !schemaLocation.matches("(?m).*spring-batch.*");
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java
index 5fa21668c3..4e2e1c3085 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java
new file mode 100644
index 0000000000..aba04df02d
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2013-2014 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
+ *
+ * https://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.core.configuration.xml;
+
+import java.util.List;
+
+import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
+import org.springframework.beans.factory.config.TypedStringValue;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
+
+public class ExceptionElementParser {
+
+ public ManagedMap parse(Element element, ParserContext parserContext, String exceptionListName) {
+ List children = DomUtils.getChildElementsByTagName(element, exceptionListName);
+ if (children.size() == 1) {
+ ManagedMap map = new ManagedMap<>();
+ Element exceptionClassesElement = children.get(0);
+ addExceptionClasses("include", true, exceptionClassesElement, map, parserContext);
+ addExceptionClasses("exclude", false, exceptionClassesElement, map, parserContext);
+ map.put(new TypedStringValue(ForceRollbackForWriteSkipException.class.getName(), Class.class), true);
+ return map;
+ }
+ else if (children.size() > 1) {
+ parserContext.getReaderContext().error(
+ "The <" + exceptionListName + "/> element may not appear more than once in a single <"
+ + element.getNodeName() + "/>.", element);
+ }
+ return null;
+ }
+
+ private void addExceptionClasses(String elementName, boolean include, Element exceptionClassesElement,
+ ManagedMap map, ParserContext parserContext) {
+ for (Element child : DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) {
+ String className = child.getAttribute("class");
+ map.put(new TypedStringValue(className, Class.class), include);
+ }
+ }
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java
index c13e75d2a6..06fb7176da 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -26,7 +26,7 @@
import org.w3c.dom.Element;
/**
- * Internal parser for the <flow/> elements inside a job..
+ * Internal parser for the <flow/> elements inside a job.
*
* @see JobParser
*
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java
index 49a88311c2..8d15602302 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2006-2008 the original author or authors.
+ * Copyright 2006-2014 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
+ * https://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,
@@ -15,23 +15,25 @@
*/
package org.springframework.batch.core.configuration.xml;
+import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
* @author Dave Syer
- *
+ * @author Michael Minella
+ *
*/
public class InlineFlowParser extends AbstractFlowParser {
-
private final String flowName;
/**
* Construct a {@link InlineFlowParser} with the specified name and using the
* provided job repository ref.
- *
+ *
* @param flowName the name of the flow
* @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean}
* from the enclosing tag
@@ -42,19 +44,23 @@ public InlineFlowParser(String flowName, String jobFactoryRef) {
}
+ @Override
+ protected boolean shouldGenerateId() {
+ return true;
+ }
+
/**
* @param element the top level element containing a flow definition
* @param parserContext the {@link ParserContext}
*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
-
builder.getRawBeanDefinition().setAttribute("flowName", flowName);
builder.addPropertyValue("name", flowName);
+ builder.addPropertyValue("stateTransitionComparator", new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR));
super.doParse(element, parserContext, builder);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.popAndRegisterContainingComponent();
}
-
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java
index 75b4532d00..e8e8fa9985 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java
index 7065b75f67..ddd61ff0a8 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -32,7 +32,7 @@
public class JobExecutionListenerParser extends AbstractListenerParser {
@Override
- protected Class extends AbstractListenerFactoryBean> getBeanClass() {
+ protected Class extends AbstractListenerFactoryBean>> getBeanClass() {
return JobListenerFactoryBean.class;
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java
index a89cdf3c0e..7edab3740a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -32,7 +32,7 @@
import org.w3c.dom.Element;
/**
- * Parser for the lt;job/gt; element in the Batch namespace. Sets up and returns
+ * Parser for the <job/> element in the Batch namespace. Sets up and returns
* a bean definition for a {@link org.springframework.batch.core.Job}.
*
* @author Dave Syer
@@ -63,14 +63,14 @@ protected Class getBeanClass(Element element) {
* @see AbstractSingleBeanDefinitionParser#doParse(Element, ParserContext,
* BeanDefinitionBuilder)
*/
- @SuppressWarnings("unchecked")
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
if (!CoreNamespaceUtils.namespaceMatchesVersion(element)) {
parserContext.getReaderContext().error(
- "You cannot use spring-batch-2.0.xsd with Spring Batch 2.1. Please upgrade your schema declarations "
- + "(or use the spring-batch.xsd alias if you are feeling lucky).", element);
+ "You are using a version of the spring-batch XSD that is not compatible with Spring Batch 3.0." +
+ " Please upgrade your schema declarations (or use the spring-batch.xsd alias if you are " +
+ "feeling lucky).", element);
return;
}
@@ -133,7 +133,7 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(),
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
- ManagedList listeners = new ManagedList();
+ ManagedList listeners = new ManagedList<>();
listeners.setMergeEnabled(listenersElement.hasAttribute(MERGE_ATTR)
&& Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR)));
List listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener");
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
index 202281f631..d099f029be 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -35,7 +35,7 @@
* @author Dave Syer
* @since 2.0.1
*/
-class JobParserJobFactoryBean implements SmartFactoryBean {
+public class JobParserJobFactoryBean implements SmartFactoryBean {
private String name;
@@ -56,7 +56,7 @@ public JobParserJobFactoryBean(String name) {
}
@Override
- public final Object getObject() throws Exception {
+ public final FlowJob getObject() throws Exception {
Assert.isTrue(StringUtils.hasText(name), "The job must have an id.");
FlowJob flowJob = new FlowJob(name);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java
index 6d81f82f25..b2a36074e6 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -27,7 +27,7 @@
import org.w3c.dom.Element;
/**
- * Parser for the lt;job-repository/gt; element in the Batch namespace. Sets up
+ * Parser for the <job-repository/> element in the Batch namespace. Sets up
* and returns a JobRepositoryFactoryBean.
*
* @author Thomas Risberg
@@ -65,6 +65,8 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit
CoreNamespaceUtils.autoregisterBeansForNamespace(parserContext, element);
String dataSource = element.getAttribute("data-source");
+
+ String jdbcOperations = element.getAttribute("jdbc-operations");
String transactionManager = element.getAttribute("transaction-manager");
@@ -82,6 +84,9 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit
builder.addPropertyValue("dataSource", ds);
RuntimeBeanReference tx = new RuntimeBeanReference(transactionManager);
builder.addPropertyValue("transactionManager", tx);
+ if (StringUtils.hasText(jdbcOperations)) {
+ builder.addPropertyReference("jdbcOperations", jdbcOperations);
+ }
if (StringUtils.hasText(isolationLevelForCreate)) {
builder.addPropertyValue("isolationLevelForCreate", DefaultTransactionDefinition.PREFIX_ISOLATION
+ isolationLevelForCreate);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java
index b963d1d052..daf7914d72 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2012-2013 the original author or authors.
+ * Copyright 2012-2014 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
+ * https://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,
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import org.springframework.batch.core.job.flow.Flow;
@@ -40,10 +41,9 @@
* that form, in which case it is not modified).
*
* @author Dave Syer
- *
+ * @author Michael Minella
*/
-@SuppressWarnings("rawtypes")
-public class SimpleFlowFactoryBean implements FactoryBean, InitializingBean {
+public class SimpleFlowFactoryBean implements FactoryBean, InitializingBean {
private String name;
@@ -51,6 +51,25 @@ public class SimpleFlowFactoryBean implements FactoryBean, InitializingBean {
private String prefix;
+ private Comparator stateTransitionComparator;
+
+ private Class flowType;
+
+ /**
+ * @param stateTransitionComparator {@link Comparator} implementation that addresses
+ * the ordering of state evaluation
+ */
+ public void setStateTransitionComparator(Comparator stateTransitionComparator) {
+ this.stateTransitionComparator = stateTransitionComparator;
+ }
+
+ /**
+ * @param flowType Used to inject the type of flow (regular Spring Batch or JSR-352)
+ */
+ public void setFlowType(Class flowType) {
+ this.flowType = flowType;
+ }
+
/**
* The name of the flow that is created by this factory.
*
@@ -75,19 +94,27 @@ public void setStateTransitions(List stateTransitions) {
/**
* Check mandatory properties (name).
*
- * @throws Exception
+ * @throws Exception thrown if error occurs.
*/
@Override
public void afterPropertiesSet() throws Exception {
Assert.hasText(name, "The flow must have a name");
+
+ if(flowType == null) {
+ flowType = SimpleFlow.class;
+ }
}
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
@Override
- public Object getObject() throws Exception {
+ public SimpleFlow getObject() throws Exception {
+ SimpleFlow flow = flowType.getConstructor(String.class).newInstance(name);
- SimpleFlow flow = new SimpleFlow(name);
+ flow.setStateTransitionComparator(stateTransitionComparator);
- List updatedTransitions = new ArrayList();
+ List updatedTransitions = new ArrayList<>();
for (StateTransition stateTransition : stateTransitions) {
State state = getProxyState(stateTransition.getState());
updatedTransitions.add(StateTransition.switchOriginAndDestination(stateTransition, state,
@@ -122,11 +149,25 @@ private State getProxyState(State state) {
}
String stateName = prefix + oldName;
if (state instanceof StepState) {
- return new StepState(stateName, ((StepState) state).getStep());
+ return createNewStepState(state, oldName, stateName);
}
return new DelegateState(stateName, state);
}
+ /**
+ * Provides an extension point to provide alternative {@link StepState}
+ * implementations within a {@link SimpleFlow}
+ *
+ * @param state The state that will be used to create the StepState
+ * @param oldName The name to be replaced
+ * @param stateName The name for the new State
+ * @return a state for the requested data
+ */
+ protected State createNewStepState(State state, String oldName,
+ String stateName) {
+ return new StepState(stateName, ((StepState) state).getStep(oldName));
+ }
+
@Override
public Class> getObjectType() {
return SimpleFlow.class;
@@ -144,7 +185,7 @@ public boolean isSingleton() {
* @author Dave Syer
*
*/
- private static class DelegateState extends AbstractState implements FlowHolder {
+ public static class DelegateState extends AbstractState implements FlowHolder {
private final State state;
private DelegateState(String name, State state) {
@@ -152,6 +193,10 @@ private DelegateState(String name, State state) {
this.state = state;
}
+ public State getState() {
+ return this.state;
+ }
+
@Override
public boolean isEndState() {
return state.isEndState();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java
index 5209dc22bf..e364fcc402 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java
@@ -5,7 +5,7 @@
* 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
+ * https://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,
@@ -44,9 +44,6 @@
*/
public class SplitParser {
- /**
- *
- */
private static final String PARENT_ATTR = "parent";
private final String jobFactoryRef;
@@ -84,15 +81,13 @@ public Collection parse(Element element, ParserContext parserCon
stateBuilder.addPropertyValue("taskExecutor", taskExecutorRef);
}
- @SuppressWarnings("unchecked")
List flowElements = DomUtils.getChildElementsByTagName(element, "flow");
if (flowElements.size() < 2) {
parserContext.getReaderContext().error("A must contain at least two 'flow' elements.", element);
}
- @SuppressWarnings("unchecked")
- Collection