From e693879144bf96bb593b46f0fe8ae1e717a77c6c Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Fri, 22 Sep 2023 13:25:26 +0200 Subject: [PATCH] Add java configuration for the Football Job sample Issue #3663 --- spring-batch-samples/README.md | 281 +--------------- .../football/FootballJobConfiguration.java | 150 +++++++++ .../sample/{domain => }/football/Game.java | 2 +- .../sample/{domain => }/football/Player.java | 4 +- .../{domain => }/football/PlayerDao.java | 2 +- .../{domain => }/football/PlayerSummary.java | 2 +- .../batch/sample/football/README.md | 301 ++++++++++++++++++ .../internal/FootballExceptionHandler.java | 2 +- .../football/internal/GameFieldSetMapper.java | 4 +- .../football/internal/JdbcGameDao.java | 4 +- .../football/internal/JdbcPlayerDao.java | 6 +- .../internal/JdbcPlayerSummaryDao.java | 4 +- .../internal/PlayerFieldSetMapper.java | 4 +- .../football/internal/PlayerItemWriter.java | 6 +- .../internal/PlayerSummaryMapper.java | 7 +- .../internal/PlayerSummaryRowMapper.java | 7 +- .../batch/sample/football-job-context.xml | 9 - .../sample/football/data}/games-small.csv | 0 .../batch/sample/football/data}/games.csv | 0 .../data}/player-containsBadRecords.csv | 0 .../sample/football/data}/player-small1.csv | 0 .../sample/football/data}/player-small2.csv | 0 .../batch/sample/football/data}/player.csv | 0 .../sample/football/job}/footballJob.xml | 45 +-- .../batch/sample/football/sql/schema.sql | 45 +++ .../images/spring-batch-football-graph.jpg | Bin 24525 -> 0 bytes .../FootballJobFunctionalTests.java | 31 +- .../internal/JdbcGameDaoIntegrationTests.java | 4 +- .../JdbcPlayerDaoIntegrationTests.java | 4 +- .../JdbcPlayerSummaryDaoIntegrationTests.java | 4 +- 30 files changed, 569 insertions(+), 359 deletions(-) create mode 100644 spring-batch-samples/src/main/java/org/springframework/batch/sample/football/FootballJobConfiguration.java rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/Game.java (98%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/Player.java (94%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/PlayerDao.java (92%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/PlayerSummary.java (98%) create mode 100644 spring-batch-samples/src/main/java/org/springframework/batch/sample/football/README.md rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/FootballExceptionHandler.java (94%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/GameFieldSetMapper.java (92%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcGameDao.java (94%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcPlayerDao.java (88%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcPlayerSummaryDao.java (94%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/PlayerFieldSetMapper.java (90%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/PlayerItemWriter.java (84%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/PlayerSummaryMapper.java (86%) rename spring-batch-samples/src/main/java/org/springframework/batch/sample/{domain => }/football/internal/PlayerSummaryRowMapper.java (86%) delete mode 100644 spring-batch-samples/src/main/resources/org/springframework/batch/sample/football-job-context.xml rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/games-small.csv (100%) rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/games.csv (100%) rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/player-containsBadRecords.csv (100%) rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/player-small1.csv (100%) rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/player-small2.csv (100%) rename spring-batch-samples/src/main/resources/{data/footballjob/input => org/springframework/batch/sample/football/data}/player.csv (100%) rename spring-batch-samples/src/main/resources/{jobs => org/springframework/batch/sample/football/job}/footballJob.xml (65%) create mode 100644 spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/sql/schema.sql delete mode 100644 spring-batch-samples/src/site/resources/images/spring-batch-football-graph.jpg rename spring-batch-samples/src/test/java/org/springframework/batch/sample/{ => football}/FootballJobFunctionalTests.java (56%) rename spring-batch-samples/src/test/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcGameDaoIntegrationTests.java (96%) rename spring-batch-samples/src/test/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcPlayerDaoIntegrationTests.java (94%) rename spring-batch-samples/src/test/java/org/springframework/batch/sample/{domain => }/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java (94%) diff --git a/spring-batch-samples/README.md b/spring-batch-samples/README.md index ec763cbcc..77eac1ef5 100644 --- a/spring-batch-samples/README.md +++ b/spring-batch-samples/README.md @@ -225,285 +225,10 @@ object ### Football Job -This is a (American) Football statistics loading job. We gave it the -id of `footballJob` in our configuration file. Before diving -into the batch job, we'll examine the two input files that need to -be loaded. First is `player.csv`, which can be found in the -samples project under -src/main/resources/data/footballjob/input/. Each line within this -file represents a player, with a unique id, the player’s name, -position, etc: +This is a (American) Football statistics loading job. It loads two files containing players and games +data into a database, and then combines them to summarise how each player performed for a particular year. - AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996 - AbduRa00,Abdullah,Rabih,rb,1975,1999 - AberWa00,Abercrombie,Walter,rb,1959,1982 - AbraDa00,Abramowicz,Danny,wr,1945,1967 - AdamBo00,Adams,Bob,te,1946,1969 - AdamCh00,Adams,Charlie,wr,1979,2003 - ... - -One of the first noticeable characteristics of the file is that each -data element is separated by a comma, a format most are familiar -with known as 'CSV'. Other separators such as pipes or semicolons -could just as easily be used to delineate between unique -elements. In general, it falls into one of two types of flat file -formats: delimited or fixed length. (The fixed length case was -covered in the `fixedLengthImportJob`. - -The second file, 'games.csv' is formatted the same as the previous -example, and resides in the same directory: - - AbduKa00,1996,mia,10,nwe,0,0,0,0,0,29,104,,16,2 - AbduKa00,1996,mia,11,clt,0,0,0,0,0,18,70,,11,2 - AbduKa00,1996,mia,12,oti,0,0,0,0,0,18,59,,0,0 - AbduKa00,1996,mia,13,pit,0,0,0,0,0,16,57,,0,0 - AbduKa00,1996,mia,14,rai,0,0,0,0,0,18,39,,7,0 - AbduKa00,1996,mia,15,nyg,0,0,0,0,0,17,96,,14,0 - ... - -Each line in the file represents an individual player's performance -in a particular game, containing such statistics as passing yards, -receptions, rushes, and total touchdowns. - -Our example batch job is going to load both files into a database, -and then combine each to summarise how each player performed for a -particular year. Although this example is fairly trivial, it shows -multiple types of input, and the general style is a common batch -scenario. That is, summarising a very large dataset so that it can -be more easily manipulated or viewed by an online web-based -application. In an enterprise solution the third step, the reporting -step, could be implemented through the use of Eclipse BIRT or one of -the many Java Reporting Engines. Given this description, we can then -easily divide our batch job up into 3 'steps': one to load the -player data, one to load the game data, and one to produce a summary -report: - -**Note:** One of the nice features of Spring is a project called -Spring IDE. When you download the project you can install Spring -IDE and add the Spring configurations to the IDE project. This is -not a tutorial on Spring IDE but the visual view into Spring beans -is helpful in understanding the structure of a Job -Configuration. Spring IDE produces the following diagram: - -![Spring Batch Football Object Model](src/site/resources/images/spring-batch-football-graph.jpg "Spring Batch Football Object Model") - -This corresponds exactly with the `footballJob.xml` job -configuration file which can be found in the jobs folder under -`src/main/resources`. When you drill down into the football job -you will see that the configuration has a list of steps: - - - - - - - - - -A step is run until there is no more input to process, which in -this case would mean that each file has been completely -processed. To describe it in a more narrative form: the first step, -playerLoad, begins executing by grabbing one line of input from the -file, and parsing it into a domain object. That domain object is -then passed to a dao, which writes it out to the PLAYERS table. This -action is repeated until there are no more lines in the file, -causing the playerLoad step to finish. Next, the gameLoad step does -the same for the games input file, inserting into the GAMES -table. Once finished, the playerSummarization step can begin. Unlike -the first two steps, playerSummarization input comes from the -database, using a Sql statement to combine the GAMES and PLAYERS -table. Each returned row is packaged into a domain object and -written out to the PLAYER_SUMMARY table. - -Now that we've discussed the entire flow of the batch job, we can -dive deeper into the first step: playerLoad: - - - - - - - - - - - - - - - - -The root bean in this case is a `SimpleStepFactoryBean`, which -can be considered a 'blueprint' of sorts that tells the execution -environment basic details about how the batch job should be -executed. It contains four properties: (others have been removed for -greater clarity) commitInterval, startLimit, itemReader and -itemWriter . After performing all necessary startup, the framework -will periodically delegate to the reader and writer. In this way, -the developer can remain solely concerned with their business -logic. - -* *ItemReader* – the item reader is the source of the information -pipe. At the most basic level input is read in from an input -source, parsed into a domain object and returned. In this way, the -good batch architecture practice of ensuring all data has been -read before beginning processing can be enforced, along with -providing a possible avenue for reuse. - -* *ItemWriter* – this is the business logic. At a high level, -the item writer takes the item returned from the reader -and 'processes' it. In our case it's a data access object that is -simply responsible for inserting a record into the PLAYERS -table. As you can see the developer does very little. - -The application developer simply provides a job configuration with a -configured number of steps, an ItemReader associated to some type -of input source, and ItemWriter associated to some type of -output source and a little mapping of data from flat records to -objects and the pipe is ready wired for processing. - -Another property in the step configuration, the commitInterval, -gives the framework vital information about how to control -transactions during the batch run. Due to the large amount of data -involved in batch processing, it is often advantageous to 'batch' -together multiple logical units of work into one transaction, since -starting and committing a transaction is extremely expensive. For -example, in the playerLoad step, the framework calls read() on the -item reader. The item reader reads one record from the file, and -returns a domain object representation which is passed to the -processor. The writer then writes the one record to the database. It -can then be said that one iteration = one call to -`ItemReader.read()` = one line of the file. Therefore, setting -your commitInterval to 5 would result in the framework committing a -transaction after 5 lines have been read from the file, with 5 -resultant entries in the PLAYERS table. - -Following the general flow of the batch job, the next step is to -describe how each line of the file will be parsed from its string -representation into a domain object. The first thing the provider -will need is an `ItemReader`, which is provided as part of the Spring -Batch infrastructure. Because the input is flat-file based, a -`FlatFileItemReader` is used: - - - - - - - - - - - - - -There are three required dependencies of the item reader; the first -is a resource to read in, which is the file to process. The second -dependency is a `LineTokenizer`. The interface for a -`LineTokenizer` is very simple, given a string; it will return a -`FieldSet` that wraps the results from splitting the provided -string. A `FieldSet` is Spring Batch's abstraction for flat file -data. It allows developers to work with file input in much the same -way as they would work with database input. All the developers need -to provide is a `FieldSetMapper` (similar to a Spring -`RowMapper`) that will map the provided `FieldSet` into an -`Object`. Simply by providing the names of each token to the -`LineTokenizer`, the `ItemReader` can pass the -`FieldSet` into our `PlayerMapper`, which implements the -`FieldSetMapper` interface. There is a single method, -`mapLine()`, which maps `FieldSet`s the same way that -developers are comfortable mapping `ResultSet`s into Java -`Object`s, either by index or field name. This behaviour is by -intention and design similar to the `RowMapper` passed into a -`JdbcTemplate`. You can see this below: - - public class PlayerMapper implements FieldSetMapper { - - public Object mapLine(FieldSet fs) { - - if(fs == null){ - return null; - } - - Player player = new Player(); - player.setID(fs.readString("ID")); - player.setLastName(fs.readString("lastName")); - player.setFirstName(fs.readString("firstName")); - player.setPosition(fs.readString("position")); - player.setDebutYear(fs.readInt("debutYear")); - player.setBirthYear(fs.readInt("birthYear")); - - return player; - } - } - -The flow of the `ItemReader`, in this case, starts with a call -to read the next line from the file. This is passed into the -provided `LineTokenizer`. The `LineTokenizer` splits the -line at every comma, and creates a `FieldSet` using the created -`String` array and the array of names passed in. - -**Note:** it is only necessary to provide the names to create the -`FieldSet` if you wish to access the field by name, rather -than by index. - -Once the domain representation of the data has been returned by the -provider, (i.e. a `Player` object in this case) it is passed to -the `ItemWriter`, which is essentially a Dao that uses a Spring -`JdbcTemplate` to insert a new row in the PLAYERS table. - -The next step, gameLoad, works almost exactly the same as the -playerLoad step, except the games file is used. - -The final step, playerSummarization, is much like the previous two -steps, in that it reads from a reader and returns a domain object to -a writer. However, in this case, the input source is the database, -not a file: - - - - - - - - - SELECT games.player_id, games.year_no, SUM(COMPLETES), - SUM(ATTEMPTS), SUM(PASSING_YARDS), SUM(PASSING_TD), - SUM(INTERCEPTIONS), SUM(RUSHES), SUM(RUSH_YARDS), - SUM(RECEPTIONS), SUM(RECEPTIONS_YARDS), SUM(TOTAL_TD) - from games, players where players.player_id = - games.player_id group by games.player_id, games.year_no - - - - -The `JdbcCursorItemReader` has three dependences: - -* A `DataSource` -* The `RowMapper` to use for each row. -* The Sql statement used to create the cursor. - -When the step is first started, a query will be run against the -database to open a cursor, and each call to `itemReader.read()` -will move the cursor to the next row, using the provided -`RowMapper` to return the correct object. As with the previous -two steps, each record returned by the provider will be written out -to the database in the PLAYER_SUMMARY table. Finally to run this -sample application you can execute the JUnit test -`FootballJobFunctionalTests`, and you'll see an output showing -each of the records as they are processed. Please keep in mind that -AoP is used to wrap the `ItemWriter` and output each record as it -is processed to the logger, which may impact performance. +[Football Job](./src/main/java/org/springframework/batch/sample/football/README.md) ### Header Footer Sample diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/FootballJobConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/FootballJobConfiguration.java new file mode 100644 index 000000000..0b1369953 --- /dev/null +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/FootballJobConfiguration.java @@ -0,0 +1,150 @@ +package org.springframework.batch.sample.football; + +import javax.sql.DataSource; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; +import org.springframework.batch.item.database.JdbcCursorItemReader; +import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; +import org.springframework.batch.sample.football.internal.GameFieldSetMapper; +import org.springframework.batch.sample.football.internal.JdbcGameDao; +import org.springframework.batch.sample.football.internal.JdbcPlayerDao; +import org.springframework.batch.sample.football.internal.JdbcPlayerSummaryDao; +import org.springframework.batch.sample.football.internal.PlayerFieldSetMapper; +import org.springframework.batch.sample.football.internal.PlayerItemWriter; +import org.springframework.batch.sample.football.internal.PlayerSummaryMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; + +@Configuration +@EnableBatchProcessing +public class FootballJobConfiguration { + + // step 1 configuration + + @Bean + public FlatFileItemReader playerFileItemReader() { + return new FlatFileItemReaderBuilder().name("playerFileItemReader") + .resource(new ClassPathResource("org/springframework/batch/sample/football/data/player-small1.csv")) + .delimited() + .names("ID", "lastName", "firstName", "position", "birthYear", "debutYear") + .fieldSetMapper(new PlayerFieldSetMapper()) + .build(); + } + + @Bean + public PlayerItemWriter playerWriter() { + PlayerItemWriter playerItemWriter = new PlayerItemWriter(); + JdbcPlayerDao playerDao = new JdbcPlayerDao(); + playerDao.setDataSource(dataSource()); + playerItemWriter.setPlayerDao(playerDao); + return playerItemWriter; + } + + @Bean + public Step playerLoad(JobRepository jobRepository, JdbcTransactionManager transactionManager) { + return new StepBuilder("playerLoad", jobRepository).chunk(2, transactionManager) + .reader(playerFileItemReader()) + .writer(playerWriter()) + .build(); + } + + // step 2 configuration + + @Bean + public FlatFileItemReader gameFileItemReader() { + return new FlatFileItemReaderBuilder().name("gameFileItemReader") + .resource(new ClassPathResource("org/springframework/batch/sample/football/data/games-small.csv")) + .delimited() + .names("id", "year", "team", "week", "opponent", "completes", "attempts", "passingYards", "passingTd", + "interceptions", "rushes", "rushYards", "receptions", "receptionYards", "totalTd") + .fieldSetMapper(new GameFieldSetMapper()) + .build(); + } + + @Bean + public JdbcGameDao gameWriter() { + JdbcGameDao jdbcGameDao = new JdbcGameDao(); + jdbcGameDao.setDataSource(dataSource()); + return jdbcGameDao; + } + + @Bean + public Step gameLoad(JobRepository jobRepository, JdbcTransactionManager transactionManager) { + return new StepBuilder("gameLoad", jobRepository).chunk(2, transactionManager) + .reader(gameFileItemReader()) + .writer(gameWriter()) + .build(); + } + + // step 3 configuration + + @Bean + public JdbcCursorItemReader playerSummarizationSource() { + String sql = """ + SELECT GAMES.player_id, GAMES.year_no, SUM(COMPLETES), + SUM(ATTEMPTS), SUM(PASSING_YARDS), SUM(PASSING_TD), + SUM(INTERCEPTIONS), SUM(RUSHES), SUM(RUSH_YARDS), + SUM(RECEPTIONS), SUM(RECEPTIONS_YARDS), SUM(TOTAL_TD) + from GAMES, PLAYERS where PLAYERS.player_id = + GAMES.player_id group by GAMES.player_id, GAMES.year_no + """; + return new JdbcCursorItemReaderBuilder().name("playerSummarizationSource") + .ignoreWarnings(true) + .sql(sql) + .dataSource(dataSource()) + .rowMapper(new PlayerSummaryMapper()) + .build(); + } + + @Bean + public JdbcPlayerSummaryDao summaryWriter() { + JdbcPlayerSummaryDao jdbcPlayerSummaryDao = new JdbcPlayerSummaryDao(); + jdbcPlayerSummaryDao.setDataSource(dataSource()); + return jdbcPlayerSummaryDao; + } + + @Bean + public Step summarizationStep(JobRepository jobRepository, JdbcTransactionManager transactionManager) { + return new StepBuilder("summarizationStep", jobRepository) + .chunk(2, transactionManager) + .reader(playerSummarizationSource()) + .writer(summaryWriter()) + .build(); + } + + // job configuration + + @Bean + public Job job(JobRepository jobRepository, Step playerLoad, Step gameLoad, Step summarizationStep) { + return new JobBuilder("footballJob", jobRepository).start(playerLoad) + .next(gameLoad) + .next(summarizationStep) + .build(); + } + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql") + .addScript("/org/springframework/batch/sample/football/sql/schema.sql") + .build(); + } + + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + +} \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Game.java similarity index 98% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Game.java index fc01d0d03..9f68bbe65 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Game.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football; +package org.springframework.batch.sample.football; import java.io.Serializable; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Player.java similarity index 94% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Player.java index 92a2c6a7c..c89dc0c17 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/Player.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 the original author or authors. + * Copyright 2006-2023 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football; +package org.springframework.batch.sample.football; import java.io.Serializable; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerDao.java similarity index 92% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerDao.java index 4f72f8652..ff53ea975 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerDao.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football; +package org.springframework.batch.sample.football; /** * Interface for writing {@link Player} objects to arbitrary output. diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerSummary.java similarity index 98% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerSummary.java index e27775813..a2542e316 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/PlayerSummary.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football; +package org.springframework.batch.sample.football; /** * Domain object representing the summary of a given Player's year. diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/README.md b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/README.md new file mode 100644 index 000000000..905a3acdf --- /dev/null +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/README.md @@ -0,0 +1,301 @@ +# Football Job + +## About the sample + +This is a (American) Football statistics loading job. We gave it the +id of `footballJob` in our configuration file. Before diving +into the batch job, we'll examine the two input files that need to +be loaded. First is `player.csv`, which can be found in the +samples project under `src/main/resources/org/springframework/batch/sample/football/data`. +Each line within this file represents a player, with a unique id, the player’s name, position, etc: + +``` +AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996 +AbduRa00,Abdullah,Rabih,rb,1975,1999 +AberWa00,Abercrombie,Walter,rb,1959,1982 +AbraDa00,Abramowicz,Danny,wr,1945,1967 +AdamBo00,Adams,Bob,te,1946,1969 +AdamCh00,Adams,Charlie,wr,1979,2003 +... +``` + +One of the first noticeable characteristics of the file is that each +data element is separated by a comma, a format most are familiar +with known as 'CSV'. Other separators such as pipes or semicolons +could just as easily be used to delineate between unique +elements. In general, it falls into one of two types of flat file +formats: delimited or fixed length. (The fixed length case was +covered in the `fixedLengthImportJob`). + +The second file, 'games.csv' is formatted the same as the previous +example, and resides in the same directory: + +``` +AbduKa00,1996,mia,10,nwe,0,0,0,0,0,29,104,,16,2 +AbduKa00,1996,mia,11,clt,0,0,0,0,0,18,70,,11,2 +AbduKa00,1996,mia,12,oti,0,0,0,0,0,18,59,,0,0 +AbduKa00,1996,mia,13,pit,0,0,0,0,0,16,57,,0,0 +AbduKa00,1996,mia,14,rai,0,0,0,0,0,18,39,,7,0 +AbduKa00,1996,mia,15,nyg,0,0,0,0,0,17,96,,14,0 +... +``` + +Each line in the file represents an individual player's performance +in a particular game, containing such statistics as passing yards, +receptions, rushes, and total touchdowns. + +Our example batch job is going to load both files into a database, +and then combine each to summarise how each player performed for a +particular year. Although this example is fairly trivial, it shows +multiple types of input, and the general style is a common batch +scenario. That is, summarising a very large dataset so that it can +be more easily manipulated or viewed by an online web-based +application. In an enterprise solution the third step, the reporting +step, could be implemented through the use of Eclipse BIRT or one of +the many Java Reporting Engines. Given this description, we can then +easily divide our batch job up into 3 'steps': one to load the +player data, one to load the game data, and one to produce a summary +report: + +```mermaid +graph LR + A(playerLoad) --> B(gameLoad) + B --> C(playerSummarization) +``` + +This corresponds exactly with the `footballJob.xml` job configuration file which can be found in +`src/main/resources/org/springframework/batch/sample/football/job`. +When you drill down into the football job you will see that the configuration has a list of steps: + +```xml + + + + + + + +``` + +A step is run until there is no more input to process, which in +this case would mean that each file has been completely +processed. To describe it in a more narrative form: the first step, +playerLoad, begins executing by grabbing one line of input from the +file, and parsing it into a domain object. That domain object is +then passed to a dao, which writes it out to the PLAYERS table. This +action is repeated until there are no more lines in the file, +causing the playerLoad step to finish. Next, the gameLoad step does +the same for the games input file, inserting into the GAMES +table. Once finished, the playerSummarization step can begin. Unlike +the first two steps, playerSummarization input comes from the +database, using a Sql statement to combine the GAMES and PLAYERS +table. Each returned row is packaged into a domain object and +written out to the PLAYER_SUMMARY table. + +Now that we've discussed the entire flow of the batch job, we can +dive deeper into the first step: playerLoad: + +```xml + + + + + + + + + + + + + + +``` + +The root bean in this case is a `SimpleStepFactoryBean`, which +can be considered a 'blueprint' of sorts that tells the execution +environment basic details about how the batch job should be +executed. It contains four properties: (others have been removed for +greater clarity) commitInterval, startLimit, itemReader and +itemWriter . After performing all necessary startup, the framework +will periodically delegate to the reader and writer. In this way, +the developer can remain solely concerned with their business +logic. + +* *ItemReader* – the item reader is the source of the information + pipe. At the most basic level input is read in from an input + source, parsed into a domain object and returned. In this way, the + good batch architecture practice of ensuring all data has been + read before beginning processing can be enforced, along with + providing a possible avenue for reuse. + +* *ItemWriter* – this is the business logic. At a high level, + the item writer takes the item returned from the reader + and 'processes' it. In our case it's a data access object that is + simply responsible for inserting a record into the PLAYERS + table. As you can see the developer does very little. + +The application developer simply provides a job configuration with a +configured number of steps, an ItemReader associated to some type +of input source, and ItemWriter associated to some type of +output source and a little mapping of data from flat records to +objects and the pipe is ready wired for processing. + +Another property in the step configuration, the commitInterval, +gives the framework vital information about how to control +transactions during the batch run. Due to the large amount of data +involved in batch processing, it is often advantageous to 'batch' +together multiple logical units of work into one transaction, since +starting and committing a transaction is extremely expensive. For +example, in the playerLoad step, the framework calls read() on the +item reader. The item reader reads one record from the file, and +returns a domain object representation which is passed to the +processor. The writer then writes the one record to the database. It +can then be said that one iteration = one call to +`ItemReader.read()` = one line of the file. Therefore, setting +your commitInterval to 5 would result in the framework committing a +transaction after 5 lines have been read from the file, with 5 +resultant entries in the PLAYERS table. + +Following the general flow of the batch job, the next step is to +describe how each line of the file will be parsed from its string +representation into a domain object. The first thing the provider +will need is an `ItemReader`, which is provided as part of the Spring +Batch infrastructure. Because the input is flat-file based, a +`FlatFileItemReader` is used: + +```xml + + + + + + + + + + + +``` + +There are three required dependencies of the item reader; the first +is a resource to read in, which is the file to process. The second +dependency is a `LineTokenizer`. The interface for a +`LineTokenizer` is very simple, given a string; it will return a +`FieldSet` that wraps the results from splitting the provided +string. A `FieldSet` is Spring Batch's abstraction for flat file +data. It allows developers to work with file input in much the same +way as they would work with database input. All the developers need +to provide is a `FieldSetMapper` (similar to a Spring +`RowMapper`) that will map the provided `FieldSet` into an +`Object`. Simply by providing the names of each token to the +`LineTokenizer`, the `ItemReader` can pass the +`FieldSet` into our `PlayerMapper`, which implements the +`FieldSetMapper` interface. There is a single method, +`mapLine()`, which maps `FieldSet`s the same way that +developers are comfortable mapping `ResultSet`s into Java +`Object`s, either by index or field name. This behaviour is by +intention and design similar to the `RowMapper` passed into a +`JdbcTemplate`. You can see this below: + +```java +public class PlayerMapper implements FieldSetMapper { + + public Object mapLine(FieldSet fs) { + + if(fs == null){ + return null; + } + + Player player = new Player(); + player.setID(fs.readString("ID")); + player.setLastName(fs.readString("lastName")); + player.setFirstName(fs.readString("firstName")); + player.setPosition(fs.readString("position")); + player.setDebutYear(fs.readInt("debutYear")); + player.setBirthYear(fs.readInt("birthYear")); + + return player; + } +} +``` + +The flow of the `ItemReader`, in this case, starts with a call +to read the next line from the file. This is passed into the +provided `LineTokenizer`. The `LineTokenizer` splits the +line at every comma, and creates a `FieldSet` using the created +`String` array and the array of names passed in. + +**Note:** it is only necessary to provide the names to create the +`FieldSet` if you wish to access the field by name, rather +than by index. + +Once the domain representation of the data has been returned by the +provider, (i.e. a `Player` object in this case) it is passed to +the `ItemWriter`, which is essentially a Dao that uses a Spring +`JdbcTemplate` to insert a new row in the PLAYERS table. + +The next step, gameLoad, works almost exactly the same as the +playerLoad step, except the games file is used. + +The final step, playerSummarization, is much like the previous two +steps, in that it reads from a reader and returns a domain object to +a writer. However, in this case, the input source is the database, +not a file: + +```xml + + + + + + + + SELECT games.player_id, games.year_no, SUM(COMPLETES), + SUM(ATTEMPTS), SUM(PASSING_YARDS), SUM(PASSING_TD), + SUM(INTERCEPTIONS), SUM(RUSHES), SUM(RUSH_YARDS), + SUM(RECEPTIONS), SUM(RECEPTIONS_YARDS), SUM(TOTAL_TD) + from games, players where players.player_id = + games.player_id group by games.player_id, games.year_no + + + +``` + +The `JdbcCursorItemReader` has three dependencies: + +* A `DataSource` +* The `RowMapper` to use for each row. +* The Sql statement used to create the cursor. + +When the step is first started, a query will be run against the +database to open a cursor, and each call to `itemReader.read()` +will move the cursor to the next row, using the provided +`RowMapper` to return the correct object. As with the previous +two steps, each record returned by the provider will be written out +to the database in the PLAYER_SUMMARY table. + +The equivalent Java configuration of the football job can be found in +`org/springframework/batch/sample/football/FootballJobConfiguration.java`. + +## Run the sample + +You can run the sample from the command line as following: + +``` +$>cd spring-batch-samples +# Launch the sample using the XML configuration +$>../mvnw -Dtest=FootballJobFunctionalTests#testLaunchJobWithXmlConfiguration test +# Launch the sample using the Java configuration +$>../mvnw -Dtest=FootballJobFunctionalTests#testLaunchJobWithJavaConfiguration test +``` \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/FootballExceptionHandler.java similarity index 94% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/FootballExceptionHandler.java index 90f8861f0..5c96dab52 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/FootballExceptionHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/GameFieldSetMapper.java similarity index 92% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/GameFieldSetMapper.java index 4e0d44e24..2bb9287fb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/GameFieldSetMapper.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; -import org.springframework.batch.sample.domain.football.Game; +import org.springframework.batch.sample.football.Game; public class GameFieldSetMapper implements FieldSetMapper { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcGameDao.java similarity index 94% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcGameDao.java index dad2229df..809fb3a56 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcGameDao.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import org.springframework.batch.item.Chunk; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.sample.domain.football.Game; +import org.springframework.batch.sample.football.Game; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerDao.java similarity index 88% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerDao.java index ecc0260b5..63d3b94f1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerDao.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import javax.sql.DataSource; -import org.springframework.batch.sample.domain.football.Player; -import org.springframework.batch.sample.domain.football.PlayerDao; +import org.springframework.batch.sample.football.Player; +import org.springframework.batch.sample.football.PlayerDao; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDao.java similarity index 94% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDao.java index 45b407bee..388348847 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDao.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import javax.sql.DataSource; import org.springframework.batch.item.Chunk; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.sample.domain.football.PlayerSummary; +import org.springframework.batch.sample.football.PlayerSummary; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerFieldSetMapper.java similarity index 90% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerFieldSetMapper.java index 8b9a545db..406135c29 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerFieldSetMapper.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; -import org.springframework.batch.sample.domain.football.Player; +import org.springframework.batch.sample.football.Player; public class PlayerFieldSetMapper implements FieldSetMapper { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerItemWriter.java similarity index 84% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerItemWriter.java index c3b2b99fe..2bdc5e151 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerItemWriter.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import org.springframework.batch.item.Chunk; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.sample.domain.football.Player; -import org.springframework.batch.sample.domain.football.PlayerDao; +import org.springframework.batch.sample.football.Player; +import org.springframework.batch.sample.football.PlayerDao; public class PlayerItemWriter implements ItemWriter { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryMapper.java similarity index 86% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryMapper.java index 1dc5b0078..9eb2557a8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryMapper.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import java.sql.ResultSet; import java.sql.SQLException; -import org.springframework.batch.sample.domain.football.PlayerSummary; +import org.springframework.batch.sample.football.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a - * {@link org.springframework.batch.sample.domain.football.PlayerSummary} + * RowMapper used to map a ResultSet to a {@link PlayerSummary} * * @author Lucas Ward * @author Mahmoud Ben Hassine diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryRowMapper.java similarity index 86% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryRowMapper.java index 33eb01cd4..61292c041 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/football/internal/PlayerSummaryRowMapper.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import java.sql.ResultSet; import java.sql.SQLException; -import org.springframework.batch.sample.domain.football.PlayerSummary; +import org.springframework.batch.sample.football.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a - * {@link org.springframework.batch.sample.domain.football.PlayerSummary} + * RowMapper used to map a ResultSet to a {@link PlayerSummary} * * @author Lucas Ward * @author Mahmoud Ben Hassine diff --git a/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football-job-context.xml b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football-job-context.xml deleted file mode 100644 index 4939869e4..000000000 --- a/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football-job-context.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/games-small.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/games-small.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/games-small.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/games-small.csv diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/games.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/games.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/games.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/games.csv diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-containsBadRecords.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-containsBadRecords.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/player-containsBadRecords.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-containsBadRecords.csv diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small1.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-small1.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/player-small1.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-small1.csv diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small2.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-small2.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/player-small2.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player-small2.csv diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player.csv b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player.csv similarity index 100% rename from spring-batch-samples/src/main/resources/data/footballjob/input/player.csv rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/data/player.csv diff --git a/spring-batch-samples/src/main/resources/jobs/footballJob.xml b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/job/footballJob.xml similarity index 65% rename from spring-batch-samples/src/main/resources/jobs/footballJob.xml rename to spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/job/footballJob.xml index 9cd3bab22..5a66eee45 100644 --- a/spring-batch-samples/src/main/resources/jobs/footballJob.xml +++ b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/job/footballJob.xml @@ -1,13 +1,11 @@ - + @@ -29,24 +27,24 @@ - + - + - + - + - + @@ -55,14 +53,14 @@ - + - + @@ -71,7 +69,7 @@ - + @@ -80,7 +78,7 @@ - + @@ -95,25 +93,6 @@ - - - - - - - - - - - diff --git a/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/sql/schema.sql b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/sql/schema.sql new file mode 100644 index 000000000..4aab4d4ea --- /dev/null +++ b/spring-batch-samples/src/main/resources/org/springframework/batch/sample/football/sql/schema.sql @@ -0,0 +1,45 @@ +DROP TABLE PLAYERS IF EXISTS; +DROP TABLE GAMES IF EXISTS; +DROP TABLE PLAYER_SUMMARY IF EXISTS; + +CREATE TABLE PLAYERS ( + PLAYER_ID CHAR(8) NOT NULL PRIMARY KEY, + LAST_NAME VARCHAR(35) NOT NULL, + FIRST_NAME VARCHAR(25) NOT NULL, + POS VARCHAR(10) , + YEAR_OF_BIRTH BIGINT NOT NULL, + YEAR_DRAFTED BIGINT NOT NULL +) ; + +CREATE TABLE GAMES ( + PLAYER_ID CHAR(8) NOT NULL, + YEAR_NO BIGINT NOT NULL, + TEAM CHAR(3) NOT NULL, + WEEK BIGINT NOT NULL, + OPPONENT CHAR(3) , + COMPLETES BIGINT , + ATTEMPTS BIGINT , + PASSING_YARDS BIGINT , + PASSING_TD BIGINT , + INTERCEPTIONS BIGINT , + RUSHES BIGINT , + RUSH_YARDS BIGINT , + RECEPTIONS BIGINT , + RECEPTIONS_YARDS BIGINT , + TOTAL_TD BIGINT +) ; + +CREATE TABLE PLAYER_SUMMARY ( + ID CHAR(8) NOT NULL, + YEAR_NO BIGINT NOT NULL, + COMPLETES BIGINT NOT NULL , + ATTEMPTS BIGINT NOT NULL , + PASSING_YARDS BIGINT NOT NULL , + PASSING_TD BIGINT NOT NULL , + INTERCEPTIONS BIGINT NOT NULL , + RUSHES BIGINT NOT NULL , + RUSH_YARDS BIGINT NOT NULL , + RECEPTIONS BIGINT NOT NULL , + RECEPTIONS_YARDS BIGINT NOT NULL , + TOTAL_TD BIGINT NOT NULL +) ; \ No newline at end of file diff --git a/spring-batch-samples/src/site/resources/images/spring-batch-football-graph.jpg b/spring-batch-samples/src/site/resources/images/spring-batch-football-graph.jpg deleted file mode 100644 index d8898c135c96cdd8cf70679d1b87a07b04191980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24525 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 diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/FootballJobFunctionalTests.java similarity index 56% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/football/FootballJobFunctionalTests.java index d0a1a4107..628b61743 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/FootballJobFunctionalTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2022 the original author or authors. + * Copyright 2007-2023 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. @@ -13,22 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample; +package org.springframework.batch.sample.football; import javax.sql.DataSource; import org.junit.jupiter.api.Test; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.jdbc.JdbcTestUtils; import static org.junit.jupiter.api.Assertions.assertTrue; -@SpringJUnitConfig( - locations = { "/simple-job-launcher-context.xml", "/jobs/footballJob.xml", "/job-runner-context.xml" }) +@SpringJUnitConfig(locations = { "/simple-job-launcher-context.xml", + "/org/springframework/batch/sample/football/job/footballJob.xml", "/job-runner-context.xml" }) class FootballJobFunctionalTests { @Autowired @@ -42,7 +47,7 @@ class FootballJobFunctionalTests { } @Test - void testLaunchJob() throws Exception { + void testLaunchJobWithXmlConfiguration() throws Exception { JdbcTestUtils.deleteFromTables(jdbcTemplate, "PLAYERS", "GAMES", "PLAYER_SUMMARY"); jobLauncherTestUtils.launchJob(); @@ -51,4 +56,20 @@ class FootballJobFunctionalTests { assertTrue(count > 0); } + @Test + void testLaunchJobWithJavaConfiguration() throws Exception { + // given + ApplicationContext context = new AnnotationConfigApplicationContext(FootballJobConfiguration.class); + JobLauncher jobLauncher = context.getBean(JobLauncher.class); + Job job = context.getBean(Job.class); + + // when + jobLauncher.run(job, new JobParameters()); + + // then + int count = JdbcTestUtils.countRowsInTable(new JdbcTemplate(context.getBean(DataSource.class)), + "PLAYER_SUMMARY"); + assertTrue(count > 0); + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcGameDaoIntegrationTests.java similarity index 96% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcGameDaoIntegrationTests.java index ef78fecd1..9329a5859 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcGameDaoIntegrationTests.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import java.sql.ResultSet; import java.sql.SQLException; @@ -24,7 +24,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.item.Chunk; -import org.springframework.batch.sample.domain.football.Game; +import org.springframework.batch.sample.football.Game; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerDaoIntegrationTests.java similarity index 94% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerDaoIntegrationTests.java index 6f61b2e7b..f16cc7aeb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerDaoIntegrationTests.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.batch.sample.domain.football.Player; +import org.springframework.batch.sample.football.Player; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java similarity index 94% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java index 732af3ab3..bb9177c74 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.batch.sample.domain.football.internal; +package org.springframework.batch.sample.football.internal; import javax.sql.DataSource; @@ -21,7 +21,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.item.Chunk; -import org.springframework.batch.sample.domain.football.PlayerSummary; +import org.springframework.batch.sample.football.PlayerSummary; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;