Premise
As explained in How to proceed with the tutorial,
it will include implementation of the jobs for A job that inputs/outputs data by accessing a database
and <<Ch09_FileAccessJob.adoc#Ch09_FileAccessJob, A job that inputs/outputs data by accessing a file. |
Overview
Create a job that validates input data (hereafter, referred as input check).
Note that, since this section is based on TERASOLUNA Batch 5.x Development guideline, refer Input check,for details.
Background, process overview and business specifications of Description of the application to be created are given below.
Background
Some mass retail stores issue point cards for members.
Membership types include "Gold member", "normal member" and the services are provided based on the membership types.
As a part of the service, 100 points are added for "gold members" and 10 points are added for "normal members" at the end of the month,
for the members who have purchased a product during that month.
Process overview
TERASOLUNA Batch 5.x will be using in an application as a monthly batch process
which adds points based on the membership type.
Implement a process which verifies validity of whether the data exceeding upper limit value of points exists in input data.
Business specifications
Business specifications are as given below.
-
Check that points of input data do not exceed 1,000,000 points
-
When an error occurs during the check, the process terminates abnormally (No exception handling)
-
-
When the product purchasing flag is "1"(process target), points are added based on membership type
-
Add 100 points when membership type is "G"(gold member) and add 10 points when membership type is "N"(Normal member)
-
-
Product purchasing flag is updated to "0" (initial status) after adding points
-
Upper limit of points is 1,000,000 points
-
If the points exceed 1,000,000 after adding the points, they are adjusted to 1,000,000 points
Table specifications
Specifications of member information table which serve as an input and output resource are as shown below.
Since it acts as an explanation for a job which accesses the database as per Premise,
refer File specifications for resource specifications of input and output for a job accessing a file.
No | Attribute name | Column name | PK | Data type | Number of digits | Explanation |
---|---|---|---|---|---|---|
1 |
Member id |
id |
CHAR |
8 |
Represents a fixed 8 digit number which uniquely identifies a member. |
|
2 |
Membership type |
type |
- |
CHAR |
1 |
Membership types are shown below. |
3 |
Product purchasing flag |
status |
- |
CHAR |
1 |
It shows whether you have purchased a product in the month. |
4 |
Point |
point |
- |
INT |
7 |
It shows the points retained by the members. |
Job overview
The process flow and process sequence are shown below to understand the overview of the job which performs input check created here.
Since it acts as an explanation for the job which accesses a database as per Premise, it must be noted that it is likely to be different from the process flow and process sequence for the job which access the file.
Input check is classified into unit item check and correlated item check etc., however only unit item checks are handled here.
Use Bean Validation for unit item check.
For details, refer Input check classification.
Process flow overview: Overview of process flow is shown below.
- Process sequence in case of a chunk model
-
Process sequence in case of a chunk model is explained.
Since this job is explained by assuming the usage of abnormal data, the sequence diagram shows occurrence of error (abnormal termination) during input check.
When the input check is successful, process sequence after input check is same as sequence diagram of database access (Refer Job overview.
In case of chunk model, input check is performed within the timing when data is passed to ItemProcessor
.
Orange colour object represents a class to be implemented at this time.
-
A step is executed from the job.
-
Step opens the resource
-
MyBatisCursorItemReader
fetches all the member information from member_info table (issue select statement).-
Repeat subsequent process until input data is exhausted.
-
Start a framework transaction with the chunk units.
-
Repeat steps from 4 to 12 until the chunk size is achieved.
-
-
Step fetches one record of input data from
MyBatisCursorItemReader
. -
MyBatisCursorItemReader
fetches one record of input data from member_info table. -
member_info table returns input data to
MyBatisCursorItemReader
. -
MyBatisCursorItemReader
returns the input data to step. -
Step processes input data by
PointAddItemProcessor
. -
PointAddItemProcessor
requestsSpringValidator
for input check. -
SpringValidator
performs input check based on input check rules and throws an exception (ValidationException) in case an error occurs during the check. -
PointAddItemProcessor
reads input data and adds points. -
PointAddItemProcessor
returns process results to the step. -
Step outputs chunk size data by
MyBatisBatchItemWriter
. -
MyBatisBatchItemWriter
updates member information for member_info table ((issue update statement).-
When an exception occurs in the processes from 4 to 14, perform following process.
-
-
Step rolls back framework transaction.
-
Step returns an exit code (here, abnormal end: 255) to the job.
- Process sequence for a tasklet model
-
Process sequence for the tasklet model is explained.
Since this job is described assuming the usage of abnormal system data, the sequence diagram shows a case when an error has occurred in input check (Abnormal end).
When the input check is successful, process sequence after the input check is same as sequence diagram of database access (Refer Job overview).
In case of a tasklet model, input check is performed within any timing in Tasklet#execute()
.
Here, it is done immediately after fetching the data.
Orange object shows a class to be implemented at this time.
-
A step is executed from the job.
-
Step starts a framework transaction.
-
-
Step executes
PointAddTasklet
. -
PointAddTasklet
opens a resource. -
MyBatisCursorItemReader
fetches all the member information (issue select statement) from member_info table.-
Repeat steps from 5 to 13 until the input data is exhausted.
-
Repeat processes from 5 to 11 until a fixed number of records is achieved.
-
-
PointAddTasklet
fetches one record of input data fromMyBatisCursorItemReader
. -
MyBatisCursorItemReader
fetches 1 record of input data from member_info table. -
member_info table returns input data to
MyBatisCursorItemReader
. -
MyBatisCursorItemReader
returns input data to tasklet. -
PointAddTasklet
requestsSpringValidator
for input check. -
SpringValidator
performs input check based on input check rules and throws an exception (ValidationException) when an error occurs during a check. -
PointAddTasklet
reads input data and adds points. -
PointAddTasklet` outputs data of fixed records by
MyBatisBatchItemWriter``. -
MyBatisBatchItemWriter
updates member information for member_info table (issue update statement).-
When an exception occurs in the processes from 2 to 13, perform following process.
-
-
PointAddTasklet
throws an exception (Here, ValidationException) in the step. -
Step rolls back the framework transaction.
-
Step returns an exit code (Here, abnormal end: 255) to the job.
Setting for implementing input check process
Use Hibernate Validator in input check. Although it is configured already in TERASOLUNA Batch 5.x, Hibernate Validator and Bean must be defined in the dependency relation of the library. Configuration example of dependent library (pom.xml)
src/main/resources/META-INF/spring/launch-context.xml
|
How to implement a chunk model and a tasklet model are explained subsequently.
Implementation in Chunk model
Execute the job which performs input check in the chunk model, from its creation to execution using following procedure.
Defining input check rules
Assign Bean Validation annotation to the field for checking DTO class in order to perform input check.
For annotation for input checks, refer Bean Validation check rules and
Hibernate Validator check rules of TERASOLUNA Server 5.x Development Guideline.
Since it is used in common for Chunk model / Tasklet model, it can be skipped if it has already been implemented.
Here, define a check rule to check whether points exceed 1,000,000 (upper limit value).
package org.terasoluna.batch.tutorial.common.dto;
import javax.validation.constraints.Max;
public class MemberInfoDto {
private String id;
private String type;
private String status;
@Max(1000000) // (1)
private int point;
// Getter and setter are omitted.
}
Sr. No. | Explanation |
---|---|
(1) |
Assign @Max annotation which indicates that the target field is less than or equal to specified value. |
Implementation of input check process
Implement input check process in business logic class which adds the points.
Add implementation of input check process to already implemented PointAddItemProcessor
class.
Since it acts as an explanation for a job which accesses the database as per Premise, add only (1)~(3) from below
to the implementation for the job accessing the file.
// Package and the other import are omitted.
import javax.inject.Inject;
@Component
public class PointAddItemProcessor implements ItemProcessor<MemberInfoDto, MemberInfoDto> {
// Definition of constants are omitted.
@Inject // (1)
Validator<MemberInfoDto> validator; // (2)
@Override
public MemberInfoDto process(MemberInfoDto item) throws Exception {
validator.validate(item); // (3)
// The other codes of business logic are omitted.
}
}
Sr. No. | Explanation |
---|---|
(1) |
Inject an instance of |
(2) |
Set DTO to be fetched through |
(3) |
Execute |
Job execution and result verification
Execute the created job on STS and verify the results.
Execute the job from execution configuration
Execute the job from execution configuration which is created in advance.
Here, the job is executed by using abnormal data.
Since how to change input data varies according to resource (database or file) which handles a job performing input check,
execute as below.
- When input check is implemented for the job which inputs or outputs data by accessing database
-
Execute job by using execution configuration created in Execute job from execution configuration of the job which inputs or outputs data by accessing database.
In order to use abnormal system data, comment out script of normal system data and remove comment out of abnormal system data
by Database Initialize of batch-application.properties
.
# Database Initialize
tutorial.create-table.script=file:sqls/create-member-info-table.sql
#tutorial.insert-data.script=file:sqls/insert-member-info-data.sql
tutorial.insert-data.script=file:sqls/insert-member-info-error-data.sql
- When input check is implemented for the job which inputs or outputs data by accessing a file
-
Execute job by using execution configuration created in Execute job from execution configuration of the job which inputs or outputs data by accessing a file.
In order to use abnormal system data, change path of input file (inputFile) from normal system data (insert-member-info-data.csv) to abnormal system data (insert-member-info-error-data.csv), from the arguments set in execution configuration.
Verify console log
Open Console View and verify that logs of following details is output.
Here, verify that the process ends abnormally (FAILED) and
org.springframework.batch.item.validator.ValidationException
has occurred.
[2017/08/28 10:53:21] [main] [o.s.b.c.s.AbstractStep] [ERROR] Encountered an error executing step jobPointAddChunk.step01 in job jobPointAddChunk
org.springframework.batch.item.validator.ValidationException: Validation failed for org.terasoluna.batch.tutorial.common.dto.MemberInfoDto@1fde4f40:
Field error in object 'item' on field 'point': rejected value [1000001]; codes [Max.item.point,Max.point,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.point,point]; arguments []; default message [point],1000000]; default message [must be less than or equal to 1000000]
at org.springframework.batch.item.validator.SpringValidator.validate(SpringValidator.java:54)
(.. omitted)
Caused by: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'item' on field 'point': rejected value [1000001]; codes [Max.item.point,Max.point,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.point,point]; arguments []; default message [point],1000000]; default message [must be less than or equal to 1000000]
... 29 common frames omitted
[2017/08/28 10:53:21] [main] [o.s.b.c.l.s.SimpleJobLauncher] [INFO ] Job: [FlowJob: [name=jobPointAddChunk]] completed with the following parameters: [{jsr_batch_run_id=408}] and the following status: [FAILED]
[2017/08/28 10:53:21] [main] [o.s.c.s.ClassPathXmlApplicationContext] [INFO ] Closing org.springframework.context.support.ClassPathXmlApplicationContext@2145433b: startup date [Mon Aug 28 10:53:18 JST 2017]; root of context hierarchy
Verify exit code
Verify that the process has terminated abnormally, by exit code.
For verification process, refer Job execution and verification of result.
Verify that exit code (exit value) is 255 (abnormal termination).
Verify output resource
Verify output resource (database or file) using the job which implements input check.
In case of a chunk model, since an intermediate commit method is adopted, verify that update is determined upto chunk just prior to the error location part.
Verify member information table
Use Data Source Explorer and verify member information table.
Compare the contents of member information table before and after the update, and verify that the contents are in accordance with verification details.
For verification procedure, refer Refer database by using Data Source Explorer.
- Verification details
-
-
Regarding records from 1 to 10 (Records with member id from "00000001" to "00000010")
-
status column
-
Records with "0"(initial status) record should not exist
-
-
point column
-
Points should be added according to membership type as explained below
-
100 points when type column is "G" (gold member)
-
10 points when type column is "N"(normal member)
-
-
-
-
Regarding records from 11 to 15 (Records with member id from "00000011" to "00000015")
-
Should not be updated
-
-
Contents of the member information table before and after update are shown below.
Verify member information file
Compare input and output contents of member information file and verify that the contents are in accordance with the verification details.
- Verification details
-
-
Member information file is output in output directory
-
Output file: files/output/output-member-info-data.csv
-
-
Output records should contain only the records from 1 to 10 (records with member id from "00000001" to "00000010")
-
Regarding output records
-
status column
-
Records with "0"(initial status) should not exist
-
-
point column
-
Points should be added according to membership type, for adding points
-
100 points when type column is "G"(gold member)
-
10 points when type column is "N"(normal member)
-
-
-
-
Input and output details of member information file are shown below.
File fields are output in the sequence of id(member ID), type(membership type), status(product purchasing flag) and point(Points).
Implementation in Tasklet model
Operations from creation to execution of a job which performs input check in tasklet model are implemented by following procedure.
Defining input check rules
In order to perform input check, assign a Bean Validation annotation in the field for checking DTO class.
For annotation for input check, refer Bean Validation check rules
and Hibernate Validator check rules of TERASOLUNA Server 5.x Development Guideline.
Since it is used in common for chunk model / tasklet model, it can be skipped if it has already been implemented.
Here, define check rules to check whether points have exceeded 1,000,000 (upper limit).
package org.terasoluna.batch.tutorial.common.dto;
import javax.validation.constraints.Max;
public class MemberInfoDto {
private String id;
private String type;
private String status;
@Max(1000000) // (1)
private int point;
// Getter and setter are omitted.
}
Sr. No. | Explanation |
---|---|
(1) |
Assign @Max annotation which indicates that target field is less than or equal to the specified numeric value. |
Implementation of input check process
Implement input check processing in business logic class which performs point addition.
Add implementation of input check process in already implemented PointAddTasklet
class.
Since it acts as an explanation of job which accesses the database as per Premise,
only (1)~(3) below are added for the implementation in case of job accessing the file.
// Package and the other import are omitted.
import javax.inject.Inject;
@Component
public class PointAddTasklet implements Tasklet {
// Definition of constant, ItemStreamReader and ItemWriter are omitted.
@Inject // (1)
Validator<MemberInfoDto> validator; // (2)
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
MemberInfoDto item = null;
List<MemberInfoDto> items = new ArrayList<>(CHUNK_SIZE);
try {
reader.open(chunkContext.getStepContext().getStepExecution().getExecutionContext());
while ((item = reader.read()) != null) {
validator.validate(item); // (3)
// The other codes of bussiness logic are omitted.
}
writer.write(items);
} finally {
reader.close();
}
return RepeatStatus.FINISHED;
}
}
Sr. No. | Explanation |
---|---|
(1) |
Inject an instance of |
(2) |
Set a DTO to be fetched through |
(3) |
Execute |
Job execution and result verification
Execute created job on STS and verify results.
Execute job from execution configuration
Execute the job from already created execution configuration.
Here, execute the job by using abnormal system data.
Since how to change input data varies based on the resource (database or file) which handles a job implementing input check,
implement as below.
- When input check is implemented for the job which inputs or outputs data by accessing a database
-
Execute job by using execution configuration created in Execute job from execution configuration of job which inputs or outputs data by accessing database.
In order to use abnormal system data, comment out script of normal system data and remove comment out of script of abnormal system data
by Database Initialize of batch-application.properties
.
# Database Initialize
tutorial.create-table.script=file:sqls/create-member-info-table.sql
#tutorial.insert-data.script=file:sqls/insert-member-info-data.sql
tutorial.insert-data.script=file:sqls/insert-member-info-error-data.sql
- When input check is implemented for the job which inputs or outputs data by accessing a file
-
Execute job by using execution configuration created in Execute job from execution configuration of the job which inputs or outputs data by accessing a file.
In order to use abnormal data, change the path of input file (inputFile) from normal system data (insert-member-info-data.csv) to abnormal system data (insert-member-info-error-data.csv), from the arguments set in execution configuration.
Verifying console log
Open Console View and verify whether the log for following details is output.
Here, verify that process ends abnormally (FAILED) and
org.springframework.batch.item.validator.ValidationException
has occurred.
[2017/09/12 10:18:49] [main] [o.s.b.c.s.AbstractStep] [ERROR] Encountered an error executing step jobPointAddTasklet.step01 in job jobPointAddTasklet
org.springframework.batch.item.validator.ValidationException: Validation failed for org.terasoluna.batch.tutorial.common.dto.MemberInfoDto@2c383e33:
Field error in object 'item' on field 'point': rejected value [1000001]; codes [Max.item.point,Max.point,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.point,point]; arguments []; default message [point],1000000]; default message [must be less than or equal to 1000000]
at org.springframework.batch.item.validator.SpringValidator.validate(SpringValidator.java:54)
(.. omitted)
Caused by: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'item' on field 'point': rejected value [1000001]; codes [Max.item.point,Max.point,Max.int,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.point,point]; arguments []; default message [point],1000000]; default message [must be less than or equal to 1000000]
... 24 common frames omitted
[2017/09/12 10:18:49] [main] [o.s.b.c.l.s.SimpleJobLauncher] [INFO ] Job: [FlowJob: [name=jobPointAddTasklet]] completed with the following parameters: [{jsr_batch_run_id=476}] and the following status: [FAILED]
[2017/09/12 10:18:49] [main] [o.s.c.s.ClassPathXmlApplicationContext] [INFO ] Closing org.springframework.context.support.ClassPathXmlApplicationContext@735f7ae5: startup date [Tue Sep 12 10:18:47 JST 2017]; root of context hierarchy
Verifying exit codes
Verify that the process has terminated abnormally by using exit code.
For verification procedure, refer Job execution and result verification.
Verify that exit code (exit value) is 255(abnormal exit).
Verifying output resource
Verify output resource (database or file) by job which implements input check.
Since batch commit method is used in case of a tasklet model, it must be confirmed that it has not been updated at all in case an error occurs.
Verifying member information table
Use Data Source Explorer and verify member information table.
Compare contents of member information table before and after update, and verify whether the contents are in accordance with the verification details.
For verification procedure, refer Refer database by using Data Source Explorer.
- Verification details
-
-
Data should not be updated for all the records
-
Verifying member information file
Compare input and output details of member information file and verify that the contents are in accordance with the verification details.
- Verification details
-
-
Member information file is output as empty file in the output directory
-
Output file: files/output/output-member-info-data.csv
-
-