2121import static org .junit .Assert .assertTrue ;
2222
2323/**
24+ * The Batch specification provides a Chunk Oriented processing style. This style is defined by enclosing into a
25+ * transaction a set of reads, process and write operations via +javax.batch.api.chunk.ItemReader+,
26+ * +javax.batch.api.chunk.ItemProcessor+ and +javax.batch.api.chunk.ItemWriter+. Items are read one at a time, processed
27+ * and aggregated. The transaction is then committed when the defined +checkpoint-policy+ is triggered.
28+ *
29+ * The +checkpoint-policy+ can be defined as +item+ or +custom+. The +item+ policy means the chunk is checkpointed after
30+ * a specified number of items are processed. The +custom+ policy means the chunk is checkpointed according to a
31+ * checkpoint algorithm implementation. To use the +custom+ policy you also need to define a +checkpoint-algorithm+
32+ * element.
33+ *
34+ * include::myJob.xml[]
35+ *
36+ * A very simple job is defined in the +myJob.xml+ file. Just a single step with a reader, processor and writer. For
37+ * this sample, a custom checkpoint policy is going to be used. The custom policy needs to implement
38+ * +javax.batch.api.chunk.CheckpointAlgorithm+ or in alternative extend
39+ * +javax.batch.api.chunk.AbstractCheckpointAlgorithm+ that already provides empty implementations for all methods.
40+ *
41+ * include::MyCheckpointAlgorithm[]
42+ *
43+ * Note that the behaviour of this custom checkpoint algorithm could also be achieved by using the +item+ policy and
44+ * defining the +item-count+ element at the +chunk+ level.
45+ *
2446 * @author Roberto Cortez
2547 */
2648@ RunWith (Arquillian .class )
2749public class BatchChunkCheckpointTest {
50+ /**
51+ * We're just going to deploy the application as a +web archive+. Note the inclusion of the following files:
52+ *
53+ * [source,file]
54+ * ----
55+ * /META-INF/batch-jobs/myjob.xml
56+ * ----
57+ *
58+ * The +myjob.xml+ file is needed for running the batch definition.
59+ */
2860 @ Deployment
2961 public static WebArchive createDeployment () {
3062 WebArchive war = ShrinkWrap .create (WebArchive .class )
@@ -36,6 +68,15 @@ public static WebArchive createDeployment() {
3668 return war ;
3769 }
3870
71+ /**
72+ * In the test, we're just going to invoke the batch execution and wait for completion. To validate the test
73+ * expected behaviour we need to query the +Metric[]+ object available in the step execution.
74+ *
75+ * The batch process itself will read and process 10 elements from numbers 1 to 10, but only write the odd
76+ * elements. Commits are executed after 5 elements are read by the custom checkpoint algorithm.
77+ *
78+ * @throws Exception an exception if the batch could not complete successfully.
79+ */
3980 @ Test
4081 public void testBatchChunkCheckpoint () throws Exception {
4182 JobOperator jobOperator = BatchRuntime .getJobOperator ();
@@ -49,12 +90,16 @@ public void testBatchChunkCheckpoint() throws Exception {
4990 if (stepExecution .getStepName ().equals ("myStep" )) {
5091 Map <Metric .MetricType , Long > metricsMap = BatchTestHelper .getMetricsMap (stepExecution .getMetrics ());
5192
93+ // <1> The read count should be 10 elements. Check +MyItemReader+.
5294 assertEquals (10L , metricsMap .get (Metric .MetricType .READ_COUNT ).longValue ());
95+ // <2> The write count should be 5. The 10 elements are read and the checkpoint is on every 5th read.
5396 assertEquals (10L / 2L , metricsMap .get (Metric .MetricType .WRITE_COUNT ).longValue ());
97+ // <3> The commit count is equals to the write count plus 1. An empty read is executed after all reads.
5498 assertEquals (10L / 5L + 1 , metricsMap .get (Metric .MetricType .COMMIT_COUNT ).longValue ());
5599 }
56100 }
57101
102+ // <4> The checkpoint algorithm should be checked 10 times. One for each element read.
58103 assertTrue (MyCheckpointAlgorithm .checkpointCountDownLatch .await (0 , TimeUnit .SECONDS ));
59104 assertEquals (jobExecution .getBatchStatus (), BatchStatus .COMPLETED );
60105 }
0 commit comments