Chunked Step using Batch Applications in Java EE 7: Getting Started with GlassFish 4 (TOTD #211)


TOTD #192 explained the key concepts of JSR 352. This Tip Of The Day provides a working example of a how to write a simple chunk step using JSR 352 Reference Implementation integrated in GlassFish 4.

The source code for this sample application can be downloaded from here and works on GlassFish 4 b78.

As explained in TOTD #192, JSR 352 defines item-oriented processing using chunk step and task-oriented processing using batchlet step. A chunk consists of a reader that reads one item at a time, a processor that processes one item at a time, and a writer that aggregates 'chunk' number of items and then writes them out.

Here is an implementation of reader:

@Named
public class MyItemReader extends AbstractItemReader<MyInputRecord> {
   
    private final StringTokenizer tokens;
   
    public MyItemReader() {
        tokens = new StringTokenizer("1,2,3,4,5,6,7,8,9,10", ",");
    }
   
    @Override
    public MyInputRecord readItem() {
        if (tokens.hasMoreTokens()) {
            return new MyInputRecord(Integer.valueOf(tokens.nextToken()));
        }
        return null;
    }
}

Reader uses type information to specify the type of record that it is working on, MyInputRecord in this case. The readItem method returns null to indicate the end of items that can be read. In this case, a StringTokenizer is used to read the items but you can use an InputStream here if you like.

Here is an implementation of processor:

@Named
public class MyItemProcessor implements ItemProcessor<MyInputRecord,MyOutputRecord> {

    @Override
    public MyOutputRecord processItem(MyInputRecord t) {
        System.out.println("processItem: " + t);
       
        return (t.getId() % 2 == 0) ? null : new MyOutputRecord(t.getId() * 2);
    }
}

Processor uses type information to specify the type of input and output records its working on, MyInputRecord is the input record and MyOutputRecord is the output record in this case. The processItem method reads the input record and accepts only odd-numbered records. This is where your business logic would be implemented.

And here is an implementation of writer:

@Named
public class MyItemWriter extends AbstractItemWriter<MyOutputRecord> {

    @Override
    public void writeItems(List<MyOutputRecord> list) {
        System.out.println("writeItems: " + list);
    }
}

Writer uses type information as well to specify the type of output record, MyOutputRecord in this case. All these elements are tied together using "Job XML" as shown:

<job id="myJob" xmlns="http://batch.jsr352/jsl">
    <step id="myStep" >
        <chunk item-count="3">
            <reader ref="myItemReader"></reader>
            <processor ref="myItemProcessor"></processor>
            <writer ref="myItemWriter"></writer>
        </chunk>   
    </step>
</job>


Eventually, the references myItemReader, myItemProcessor, and myItemWriter will be resolved using CDI. But for now, the references can be explicitly resolved using "batch.xml" as shown:

<batch-artifacts xmlns="http://jcp.org.batch/jsl">
    <ref id="myItemReader" class="org.glassfish.chunk.simple.MyItemReader"/>
    <ref id="myItemProcessor" class="org.glassfish.chunk.simple.MyItemProcessor"/>
    <ref id="myItemWriter" class="org.glassfish.chunk.simple.MyItemWriter"/>
</batch-artifacts>


Once again, downloaded the source code from here and get it running on GlassFish 4 b78.

Post feedback on public@jbatch.java.net or users@glassfish.java.net.


Comments:

The link to the source example is broken

Posted by guest on March 21, 2013 at 11:33 PM PDT #

I could download the source code from:

https://blogs.oracle.com/arungupta/resource/totd211-chunk-simple.zip

Where do you see an incorrect link ?

Arun

Posted by Arun Gupta on March 22, 2013 at 12:45 PM PDT #

Hi Arun,
I do not see any example/hint of any scheduler for the batch jobs. In Spring, we have triggers and schedulers for this purpose. In your example, you are triggering it from a Servlet which has to be called. Do we need to use our own schedulers for this purpose or GlassFish has some support built-in for this purpose?

Thanks,
Sunil Kumar Pandey

Posted by Sunil Kumar Pandey on March 24, 2013 at 05:46 AM PDT #

Hi Arun,
This example uses a servlet to kick off the job. Is there any scheduler/trigger available in GlassFish to kick-off jobs at certain intervals or time of the day, etc. like we do for cron jobs?

Thanks,
Sunil

Posted by Sunil Kumar Pandey on March 24, 2013 at 06:23 AM PDT #

The server had an internal error on serving the zip file, now it's available, thanks for the interest though.

Posted by guest on March 24, 2013 at 04:58 PM PDT #

Sunil,

You can use EJB Timer Service that allows you to specify cron syntax for triggering these jobs. This is explained at:

https://blogs.oracle.com/arungupta/entry/totd_146_understanding_the_ejb

Posted by Arun Gupta on March 25, 2013 at 07:49 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today