Tavaszi tétel - Feladatok vs darabok

1. Bemutatkozás

A Spring Batch két különböző módot kínál a munka megvalósítására: a tasklet és a darabokat.

Ebben a cikkben megtudhatjuk, hogyan kell konfigurálni és megvalósítani mindkét módszert egy egyszerű valós példával.

2. Függőségek

Kezdjük azzal a szükséges függőségek hozzáadása:

 org.springframework.batch spring-batch-core 4.2.0.RELEASE org.springframework.batch spring-batch-test 4.2.0.RELEASE test 

A rugós kötegelt mag és a rugós köteg teszt legújabb verziójának beszerzéséhez olvassa el a Maven Central oldalt.

3. Felhasználási esetünk

Vegyünk egy CSV-fájlt a következő tartalommal:

Mae Hodges, 1972/22/22 Gary Potter, 1953/02/22 Betty Wise, 1968/02/17 Wayne Rose, 1977/06/04 Adam Caldwell, 1995/09/27 Lucille Phillips, 1992/14/14

A Minden sor első pozíciója egy személy nevét, a második pozíció pedig a születési dátumát jelöli.

Felhasználási esetünk az hozzon létre egy másik CSV fájlt, amely tartalmazza az egyes személyek nevét és életkorát:

Mae Hodges, 45 Gary Potter, 64 Betty Wise, 49 Wayne Rose, 40 Adam Caldwell, 22 Lucille Phillips, 25

Most, hogy a tartományunk tiszta, menjünk tovább, és készítsünk egy megoldást mindkét megközelítés segítségével. Kezdjük a tasklettel.

4. Feladatok megközelítése

4.1. Bevezetés és tervezés

A feladatok egyetlen feladat végrehajtását jelentik egy lépésen belül. Munkánk több lépésből áll, amelyek egymás után hajtanak végre. Minden lépésnek csak egy meghatározott feladatot kell végrehajtania.

Munkánk három lépésből áll:

  1. Sorok olvasása a bemeneti CSV fájlból.
  2. Számítsa ki a bemeneti CSV-fájlban szereplő személyek életkorát.
  3. Írja be minden személy nevét és életkorát egy új kimeneti CSV fájlba.

Most, hogy elkészült az összkép, hozzunk létre egy osztályt lépésenként.

LinesReader feladata lesz az adatok beolvasása a bemeneti fájlból:

public class LinesReader megvalósítja a Taskletet {// ...}

LinesProcessor kiszámítja a fájlban szereplő személyek életkorát:

public class LinesProcessor megvalósítja a Taskletet {// ...}

Végül, LinesWriter feladata lesz neveket és életkorokat kimeneti fájlba írni:

public class LinesWriter megvalósítja a Taskletet {// ...}

Ezen a ponton, minden lépésünk megvalósul Feladat felület. Ez arra kényszerít minket, hogy megvalósítsuk végrehajtani módszer:

@Orride public RepeatStatus execute (StepContribution stepContribution, ChunkContext chunkContext) dobja a kivételt {// ...}

Ebben a módszerben adjuk hozzá az egyes lépések logikáját. Mielőtt ezzel a kóddal kezdjük, konfiguráljuk a munkánkat.

4.2. Konfiguráció

Meg kell adjon hozzá néhány konfigurációt a Spring alkalmazáskörnyezetéhez. Az előző szakaszban létrehozott osztályok standard babdeklarációjának hozzáadása után készen állunk a feladatmeghatározásunk létrehozására:

@Configuration @EnableBatchProcessing public class TaskletsConfig {@Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory lépések; @Bean védett lépés readLines () {visszatérési lépések .get ("readLines") .tasklet (linesReader ()) .build (); } @Bean védett lépés processLines () {return steps .get ("processLines") .tasklet (linesProcessor ()) .build (); } @Bean védett lépés írási sorok () {visszatérési lépések .get ("writeLines") .tasklet (linesWriter ()) .build (); } @Bean public job job () {munkahelyek visszaadása .get ("taskletsJob") .start (readLines ()) .next (processLines ()) .next (writeLines ()) .build (); } // ...}

Ez azt jelenti, hogy a mi „TaskletsJob” három lépésből áll. Az első (readLines) végrehajtja a babban definiált feladatlapot linesReader és lépjen a következő lépésre: processLines. ProcessLines végrehajtja a babban definiált feladatlapot vonalakProcesszor és folytassa az utolsó lépéssel: writeLines.

Munkafolyamatunk meg van határozva, és készen állunk a logika hozzáadására!

4.3. Modell és segédprogramok

Mivel egy CSV-fájl sorait fogjuk manipulálni, létrehozunk egy osztályt Vonal:

public class Line megvalósítja a Serializable {private String name; magán LocalDate dob; magán Hosszú életkor; // standard konstruktor, getterek, beállítók és toString implementáció}

Kérjük, vegye figyelembe, hogy Vonal megvalósítja Sorosítható. Ez azért van, mert Vonal DTO-ként fog működni az adatok átvitele a lépések között. A Spring Batch szerint a lépések között átvitt objektumoknak sorosíthatóknak kell lenniük.

Másrészt elkezdhetünk gondolkodni a sorok olvasásán és írásán.

Ehhez felhasználjuk az OpenCSV-t:

 com.opencsv opencsv 4.1 

Keresse meg a legújabb OpenCSV verziót a Maven Central-ban.

Miután az OpenCSV bekerült, létrehozunk egy FileUtils osztály. Meg fogja adni a CSV-vonalak olvasási és írási módszereit:

public class FileUtils {public line readLine () dobja a Kivételt {if (CSVReader == null) initReader (); Karakterlánc [] sor = CSVReader.readNext (); if (line == null) return null; return new Line (sor [0], LocalDate.parse (sor [1], DateTimeFormatter.ofPattern ("HH / nn / éééé"))); } public void writeLine (Vonal) dobja a (z) {if (CSVWriter == null) initWriter () kivételt; Karakterlánc [] lineStr = új karakterlánc [2]; lineStr [0] = line.getName (); lineStr [1] = line .getAge () .toString (); CSVWriter.writeNext (lineStr); } // ...}

Figyelje meg readLine burkolóként működik az OpenCSV-k felett readNext metódus és visszatér a Vonal tárgy.

Ugyanilyen módon, writeLine becsomagolja az OpenCSV-ket writeNext fogadó a Vonal tárgy. Ennek az osztálynak a teljes megvalósítása megtalálható a GitHub Projektben.

Ezen a ponton mindannyian készen állunk az egyes lépések megvalósításának megkezdésére.

4.4. LinesReader

Menjünk előre, és fejezzük be a dolgunkat LinesReader osztály:

public class LinesReader végrehajtja a Tasklet, StepExecutionListener {private final Logger logger = LoggerFactory .getLogger (LinesReader.class); privát List sorok; privát FileUtils fu; @Orride public void beforeStep (StepExecution stepExecution) {lines = new ArrayList (); fu = new FileUtils ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("A Vonal olvasó inicializálva."); } @Override public RepeatStatus execute (StepContribution stepContribution, ChunkContext chunkContext) dobja a Kivételt {Line line = fu.readLine (); while (vonal! = null) {sorok.add (vonal); logger.debug ("Olvasási sor:" + line.toString ()); vonal = fu.readLine (); } return RepeatStatus.FINISHED; } @Orride public ExitStatus afterStep (StepExecution stepExecution) {fu.closeReader (); stepExecution .getJobExecution () .getExecutionContext () .put ("vonalak", ez.sorok); logger.debug ("A Vonal olvasó véget ért."); return ExitStatus.COMPLETED; }}

A LinesReader végrehajtja módszer létrehozza a FileUtils példány a bemeneti fájl elérési útján. Azután, sorokat ad hozzá a listához, amíg nincs több olvasnivaló sor.

Az óránk megvalósítja is StepExecutionListener amely két extra módszert kínál: előttStep és afterStep. Ezekkel a módszerekkel inicializáljuk és lezárjuk a dolgokat előtte és utána végrehajtani fut.

Ha megnézzük afterStep kódot, észrevesszük azt a sort, ahol az eredménylista (vonalak) a munka kontextusába kerül, hogy elérhetővé váljon a következő lépéshez:

stepExecution .getJobExecution () .getExecutionContext () .put ("vonalak", ez.sorok);

Ezen a ponton első lépésünk már eleget tett felelősségének: töltsön be CSV-vonalakat a Lista emlékül. Térjünk át a második lépésre és dolgozzuk fel őket.

4.5. LinesProcessor

LinesProcessor megvalósítani is fogja StepExecutionListener és természetesen, Feladat. Ez azt jelenti, hogy megvalósítja előttStep, végrehajtani és afterStep módszerek is:

public class LinesProcessor megvalósítja a Tasklet, StepExecutionListener {private Logger logger = LoggerFactory.getLogger (LinesProcessor.class); privát List sorok; @Orride public void beforeStep (StepExecution stepExecution) {ExecutionContext végrehajtásiContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (List) végrehajtásContext.get ("vonalak"); logger.debug ("A vonalak processzora inicializálva."); } @Orride public RepeatStatus execute (StepContribution stepContribution, ChunkContext chunkContext) dobja a Kivételt {for (Line line: lines) {long age = ChronoUnit.YEARS.between (line.getDob (), LocalDate.now ()); logger.debug ("Számított életkor" + életkor + "sor" + line.toString ()); line.setAge (életkor); } return RepeatStatus.FINISHED; } @Orride public ExitStatus afterStep (StepExecution stepExecution) {logger.debug ("A vonalak processzora leállt."); return ExitStatus.COMPLETED; }}

Könnyű ezt megérteni betölti vonalak listázzon a munkakörnyezetből, és kiszámolja az egyes emberek életkorát.

Nem szükséges újabb eredménylistát a kontextusba helyezni, mivel a módosítások ugyanazon az objektumon történnek, mint az előző lépésből.

És készen állunk az utolsó lépésünkre.

4.6. LinesWriter

LinesWriterFeladata, hogy átmenjen vonalak listázza és írja be a nevet és az életkort a kimeneti fájlba:

public class LinesWriter megvalósítja a Tasklet, StepExecutionListener {private final Logger logger = LoggerFactory .getLogger (LinesWriter.class); privát List sorok; privát FileUtils fu; @Orride public void beforeStep (StepExecution stepExecution) {ExecutionContext végrehajtásiContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (List) végrehajtásContext.get ("vonalak"); fu = new FileUtils ("output.csv"); logger.debug ("A vonalak írója inicializálva."); } @Override public RepeatStatus execute (StepContribution stepContribution, ChunkContext chunkContext) dobja a Kivételt {for (Line line: lines) {fu.writeLine (line); logger.debug ("Írta a sort" + line.toString ()); } return RepeatStatus.FINISHED; } @Override public ExitStatus afterStep (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("A vonalak írójának vége."); return ExitStatus.COMPLETED; }}

Befejeztük munkánk megvalósítását! Hozzunk létre egy tesztet a futtatásához és az eredmények megtekintéséhez.

4.7. A munka futtatása

A feladat futtatásához létrehozunk egy tesztet:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = TaskletsConfig.class) public class TaskletsTest {@Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test public void givenTaskletsJob_whenJobEnds_thenStatusCompleted () dobja a Kivételt {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

ContextConfiguration az annotáció a Spring kontextus konfigurációs osztályra mutat, amely megadja a munkánk definícióját.

A teszt futtatása előtt hozzá kell adnunk néhány extra babot:

@Bean public JobLauncherTestUtils jobLauncherTestUtils () {return new JobLauncherTestUtils (); } @Bean public JobRepository jobRepository () dobja a Kivételt {MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean (); factory.setTransactionManager (tranzakcióManager ()); return (JobRepository) factory.getObject (); } @Bean public PlatformTransactionManageractionManager () {return new ResourcelessTransactionManager (); } @Bean public JobLauncher jobLauncher () dobja a Kivételt {SimpleJobLauncher jobLauncher = új SimpleJobLauncher (); jobLauncher.setJobRepository (jobRepository ()); return jobLauncher; }

Minden készen áll! Folytasd és futtasd a tesztet!

A munka befejezése után output.csv a várt tartalom és a naplók megmutatják a végrehajtási folyamatot:

[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader inicializálva. [main] DEBUG obttasklets.LinesReader - Sor olvasása: [Mae Hodges, 1972.10.22.] [main] DEBUG obttasklets.LinesReader - Read line: [Gary Potter, 1953.02.22.] [main] DEBUG obttasklets .LinesReader - Olvasd el a sort: [Betty Wise, 1968.02.17.] [Main] DEBUG obttasklets.LinesReader - Read line: [Wayne Rose, 1977.06.04.] [Main] DEBUG obttasklets.LinesReader - Sor olvasása: [Adam Caldwell, 1995. 09. 27.] [main] DEBUG obttasklets.LinesReader - Read read: [Lucille Phillips, 1992.05.14.] [Main] DEBUG obttasklets.LinesReader - Lines Reader véget ért. [main] DEBUG o.b.t.tasklets.LinesProcessor - Lines processzor inicializálva. [main] DEBUG obttasklets.LinesProcessor - Számított 45 éves kor [Mae Hodges, 1972.10.22.] [main] DEBUG obttasklets.LinesProcessor - Számított életkor 64 vonal [Gary Potter, 1952.02.22.] [fő ] DEBUG obttasklets.LinesProcessor - Számított 49 éves kor [Betty Wise, 1968.02.17.] [Main] DEBUG obttasklets.LinesProcessor - Számított 40 éves kor [Wayne Rose, 1977.06.06.] [Main] DEBUG obttasklets.LinesProcessor - Számított életkor 22 vonalra [Adam Caldwell, 1995/09/27] [main] DEBUG obttasklets.LinesProcessor - Számított életkor 25 vonalra [Lucille Phillips, 1992/14/14] [main] DEBUG obttasklet .LinesProcessor - A Lines Processor leállt. [main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer inicializálva. [main] DEBUG obttasklets.LinesWriter - Írta a sort [Mae Hodges, 1972.10.22., 45.] [main] DEBUG obttasklets.LinesWriter - Írta a sort [Gary Potter, 1953.02.22., 64] [main] DEBUG obttasklets.LinesWriter - Írta a sort [Betty Wise, 1968.02.17., 49] [main] DEBUG obttasklets.LinesWriter - Írta a sort [Wayne Rose, 1977. 06. 06. 40] [main] DEBUG obttasklets.LinesWriter - Írta a sort [Adam Caldwell, 1995/09/27, 22] [main] DEBUG obttasklets.LinesWriter - Írta a sort [Lucille Phillips, 1992/14 / 14,25] [main] DEBUG obttasklets.LinesWriter - Lines Writer véget ért .

Ennyi a Taskleteknek. Most áttérhetünk a Chunks megközelítésre.

5. Darabok megközelítése

5.1. Bevezetés és tervezés

Ahogy a neve is sugallja, ez a megközelítés műveleteket hajt végre az adatcsomók felett. Vagyis ahelyett, hogy minden sort egyszerre olvasna, feldolgozna és írna, egyszerre rögzített mennyiségű rekordot (darabokat) fog olvasni, feldolgozni és írni.

Ezután megismétli a ciklust, amíg nincs több adat a fájlban.

Ennek eredményeként az áramlás kissé eltér:

  1. Amíg vannak sorok:
    • X mennyiségű sor esetén tegye:
      • Olvasson el egy sort
      • Feldolgozzon egy sort
    • Írjon X sort.

Tehát nekünk is alkotnunk kell három bab a daraborientált megközelítéshez:

nyilvános osztály LineReader {// ...}
nyilvános osztály LineProcessor {// ...}
public class LinesWriter {// ...}

Mielőtt áttérne a megvalósításra, konfiguráljuk a munkánkat.

5.2. Konfiguráció

A munkakör meghatározása is másképp fog kinézni:

@Configuration @EnableBatchProcessing public class ChunksConfig {@Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory lépések; @Bean public ItemReader itemReader () {return new LineReader (); } @Bean public ItemProcessor itemProcessor () {return new LineProcessor (); } @Bean public ItemWriter itemWriter () {return new LinesWriter (); } @Bean védett lépés processLines (ItemReader olvasó, ItemProcessor processzor, ItemWriter író) {return steps.get ("processLines"). darab (2) .olvasó (olvasó) .processzor (processzor) .író (író) .build (); } @Bean public job job () {munkahelyek visszaadása .get ("chunksJob") .start (processLines (itemReader (), itemProcessor (), itemWriter ())) .build (); }}

Ebben az esetben csak egy lépés van, és csak egy feladatfüzetet hajt végre.

Azonban az a feladatlap meghatározza az olvasókat, az írókat és a processzorokat, amelyek az adatok darabjaira hatnak.

Vegye figyelembe, hogy a a végrehajtási intervallum az egy darabban feldolgozandó adatmennyiséget jelzi. A munkánk egyszerre két sort fog olvasni, feldolgozni és írni.

Most készen állunk a darabos logikánk hozzáadására!

5.3. LineReader

LineReader feladata lesz egy lemez elolvasása és a Vonal például a tartalmával.

Olvasóvá válni, osztályunknak végre kell hajtania ItemReader felület:

public class LineReader megvalósítja a ItemReader {@Orride public line read () dobja a Kivételt {Line line = fu.readLine (); if (line! = null) logger.debug ("Olvasd el a sort:" + line.toString ()); visszatérő vonal; }}

A kód egyértelmű, csak egy sort olvas és visszaadja. Meg is valósítjuk StepExecutionListener az osztály végleges változatához:

public class LineReader megvalósítja a ItemReader, StepExecutionListener {private final Logger logger = LoggerFactory .getLogger (LineReader.class); privát FileUtils fu; @Orride public void beforeStep (StepExecution stepExecution) {fu = new FileUtils ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("A vonalas olvasó inicializálva."); } @Orride public Line read () dobja a {Line line = fu.readLine () kivételt; if (line! = null) logger.debug ("Olvasd el a sort:" + line.toString ()); visszatérő vonal; } @Orride public ExitStatus afterStep (StepExecution stepExecution) {fu.closeReader (); logger.debug ("Véget ért a sorolvasó."); return ExitStatus.COMPLETED; }}

Ezt észre kell venni beforeStep és afterStep végre kell hajtani az egész lépés előtt, illetve után.

5.4. LineProcessor

LineProcessor nagyjából ugyanazt a logikát követi, mint LineReader.

Ebben az esetben azonban megvalósítjuk ItemProcessor és annak módszere folyamat():

public class LineProcessor megvalósítja az ItemProcessor {private Logger logger = LoggerFactory.getLogger (LineProcessor.class); A @Orride public line process (Line line) kivételt dob ​​a {long age = ChronoUnit.YEARS. Között (line.getDob (), LocalDate.now ()); logger.debug ("Számított életkor" + életkor + "sor" + line.toString ()); line.setAge (életkor); visszatérő vonal; }}

A folyamat() A method felvesz egy beviteli sort, feldolgozza és kimeneti sort ad vissza. Ismét megvalósítjuk StepExecutionListener:

public class LineProcessor megvalósítja az ItemProcessor, StepExecutionListener {private Logger logger = LoggerFactory.getLogger (LineProcessor.class); @Orride public void beforeStep (StepExecution stepExecution) {logger.debug ("A vonal processzor inicializálva."); } @Orride public line process (Line line) dobja a {long age = ChronoUnit.YEARS. Kivétel (line.getDob (), LocalDate.now ()) kivételt; logger.debug ("Számított életkor" + életkor + "sor" + line.toString ()); line.setAge (életkor); visszatérő vonal; } @Orride public ExitStatus afterStep (StepExecution stepExecution) {logger.debug ("A vonalprocesszor leállt."); return ExitStatus.COMPLETED; }}

5.5. LinesWriter

Az olvasóval és a processzorral ellentétben LinesWriter egy egész sort fog írni hogy megkapja a Lista nak,-nek Vonalak:

public class LinesWriter megvalósítja a ItemWriter, StepExecutionListener {private final Logger logger = LoggerFactory .getLogger (LinesWriter.class); privát FileUtils fu; @Orride public void beforeStep (StepExecution stepExecution) {fu = new FileUtils ("output.csv"); logger.debug ("A vonalkód inicializálva."); } @Orride public void write (Sorok felsorolása) dobja a Kivételt {a (Vonal: sorok) {fu.writeLine (sor); logger.debug ("Írta a sort" + line.toString ()); }} @Override public ExitStatus afterStep (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("A vonalkód leállt."); return ExitStatus.COMPLETED; }}

LinesWriter kód önmagáért beszél. És ismét készen állunk a munkánk tesztelésére.

5.6. A munka futtatása

Létrehozunk egy új tesztet, amelyet a tasklets megközelítéshez készítettünk:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = ChunksConfig.class) public class ChunksTest {@Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test public void givenChunksJob_whenJobEnds_thenStatusCompleted () dobja a Kivételt {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

Konfigurálás után ChunksConfig amint azt fentebb kifejtettük TaskletsConfig, mindannyian készen állunk a teszt futtatására!

A munka elvégzése után ezt láthatjuk output.csv ismét tartalmazza a várt eredményt, és a naplók leírják a folyamatot:

[main] DEBUG o.b.t.chunks.LineReader - A sorolvasó inicializálva van. [main] DEBUG o.b.t.chunks.LinesWriter - A vonalkód inicializálva van. [main] DEBUG o.b.t.chunks.LineProcessor - Vonalfeldolgozó inicializálva. [main] DEBUG obtchunks.LineReader - Olvasd el a sort: [Mae Hodges, 1972.10.10.] [main] DEBUG obtchunks.LineReader - Olvasd a sort: [Gary Potter, 1953.02.22.] [main] DEBUG obtchunks .LineProcessor - Számított 45 éves kor [Mae Hodges, 1972.10.22.] [Main] DEBUG obtchunks.LineProcessor - Számított életkor 64 vonal [Gary Potter, 1953.02.22.] [Main] DEBUG obtchunks.LinesWriter - Írta a sort [Mae Hodges, 1972.10.22., 45] [main] DEBUG obtchunks.LinesWriter - Írta a sort [Gary Potter, 1953.02.22., 64] [main] DEBUG obtchunks.LineReader - Sor olvasása: [Betty Wise, 1968.02.17.] [Main] DEBUG obtchunks.LineReader - Read read: [Wayne Rose, 1977.06.04.] [Main] DEBUG obtchunks.LineProcessor - 49-es számított életkor [Betty Wise, 1968.02.17.] [Main] DEBUG obtchunks.LineProcessor - 40 éves életkor kiszámítása [Wayne Rose, 1977.06.04.] [Main] DEBUG obtchunks.LinesWriter - Sor írása [Betty Wise, 1968.02.17. , 49] [main] DEBUG obtchunks.LinesWriter - Sorot írt [Wayne Rose, 1977.06.06., 40] [main] DEBUG ob t.chunks.LineReader - Olvasd el a sort: [Adam Caldwell, 1995. 09. 27.] [main] DEBUG obtchunks.LineReader - Read line: [Lucille Phillips, 1992.05.14.] [main] DEBUG obtchunks.LineProcessor - Számított 22 éves kor a vonalon [Adam Caldwell, 09/27/1995] [main] DEBUG obtchunks.LineProcessor - Számított 25 éves kor a vonalon [Lucille Phillips, 05/14/1992] [main] DEBUG obtchunks.LinesWriter - Írta a sort [Adam Caldwell, 1995/09/27, 22] [main] DEBUG obtchunks.LinesWriter - Írta a sort [Lucille Phillips, 1992.05.14., 25] [main] DEBUG obtchunks.LineProcessor - Vonalfeldolgozó lejárt. [main] DEBUG o.b.t.chunks.LinesWriter - A Line Writer befejeződött. [main] DEBUG o.b.t.chunks.LineReader - Véget ért a sorolvasó.

Ugyanaz az eredményünk és más az áramlásunk. A naplók nyilvánvalóvá teszik a feladat végrehajtását ennek a megközelítésnek megfelelően.

6. Következtetés

Különböző összefüggések mutatják be az egyik vagy másik megközelítés szükségességét. Míg a Tasklet természetesebbnek érzi az „egyik a másik után a feladatot” forgatókönyveket, a darabok egyszerű megoldást kínálnak a lapozott olvasások vagy olyan helyzetek kezelésére, amikor nem akarunk jelentős mennyiségű adatot a memóriában tartani.

Ennek a példának a teljes megvalósítása megtalálható a a GitHub projekt.