X

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

Guest Author


href="https://blogs.oracle.com/arungupta/entry/batch_applications_in_java_ee">TOTD
#192 explained the key concepts of href="http://jcp.org/en/jsr/detail?id=352">JSR 352. This Tip
Of The Day provides a working example of a
how to write a simple chunk step using href="http://java.net/projects/jbatch/">JSR 352 Reference
Implementation integrated in href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/">GlassFish
4.



The source code for this sample application can be href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/09136a8d365fd29ece7937ea4553da89/totd211_chunk_simple.zip">downloaded
from here and works on href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/glassfish-4.0-b78.zip">GlassFish
4 b78.



As explained in href="https://blogs.oracle.com/arungupta/entry/batch_applications_in_java_ee">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 href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/09136a8d365fd29ece7937ea4553da89/totd211_chunk_simple.zip">from
here and get it running on href="http://dlc.sun.com.edgesuite.net/glassfish/4.0/promoted/glassfish-4.0-b78.zip">GlassFish
4 b78.



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




Join the discussion

Comments ( 6 )
  • guest Friday, March 22, 2013

    The link to the source example is broken


  • Arun Gupta Friday, March 22, 2013

    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


  • Sunil Kumar Pandey Sunday, March 24, 2013

    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


  • Sunil Kumar Pandey Sunday, March 24, 2013

    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


  • guest Sunday, March 24, 2013

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


  • Arun Gupta Monday, March 25, 2013

    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


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.