Nykyaikana internet on muuttanut tapaa, jolla elämme elämäämme, ja yksi tärkeimmistä syistä siihen on internetin käyttö useimpiin päivittäisiin askareisiin. Tämä johtaa valtavaan tietomäärään, jota voidaan käsitellä.
Joitakin esimerkkejä, joissa on kyse valtavasta tietomäärästä, ovat palkkatodistusten, tiliotteiden, korkolaskelmien jne. käsittely. Kuvittele siis, että jos kaikki nämä työt pitäisi tehdä manuaalisesti, kestää ikuisuuksia saada nämä työt valmiiksi.
Miten se tehdään nykyaikana? Vastaus on Eräkäsittely.
- Esittely
- 1.1 Java-eräkäsittelyn historia
- 1.2 Java-eräkäsittelyn arkkitehtuuri
- 1.3 Eräkäsittelyn komponentit.
- 1.3 Työn vaiheet
- 1.3.1 Palikkapainotteiset askeleet
- 1.3.2 Tehtäväkeskeiset askeleet
- 1.3.3 Rinnakkaiskäsittely
- Työkalut ja teknologiat
- Projektin rakenne
- Ohjelman tavoite
- 4.1 Gradle build
- 4.2 Esimerkkidatatiedosto
- 4.3 SQL-skriptit
- 4.4 Model Class
- 4.5 Konfiguraatioluokka
- 4.6 Elementtiprosessori
- 4.7 JobExecutionSupportListener-luokka
- 4.8 Sovellusluokka
- Output
- Yhteenveto
- 7. Lataa Eclipse-projekti
Esittely
Eräkäsittely suoritetaan massatiedoille, ilman manuaalisia toimenpiteitä ja pitkäkestoisesti. Se voi olla data- tai laskentaintensiivinen. Eräkäsittelytyöt voidaan suorittaa ennalta määritellyn aikataulun mukaan tai ne voidaan käynnistää pyynnöstä. Koska erätyöt ovat yleensä pitkäkestoisia töitä, myös jatkuvat tarkistukset ja uudelleenkäynnistyminen tietystä vikatilanteesta ovat yleisiä erätöissä esiintyviä ominaisuuksia.
1.1 Java-eräkäsittelyn historia
Java-alustan eräkäsittely otettiin käyttöön osana Java EE 7 -alustaan kuuluvaa JSR 352 -määrittelyä, jossa määritellään ohjelmointimalli eräsovelluksille sekä ajoaika erätöiden suorittamiseen ja hallintaan.
1.2 Java-eräkäsittelyn arkkitehtuuri
Alhaalla olevassa kaaviossa näkyvät eräkäsittelyn peruskomponentit.
Javan eräkäsittelyn arkkitehtuuri
Eräkäsittelysovellusten arkkitehtuuri ratkaisee eräkäsittelyyn liittyvät ongelmat, kuten työt, askeleet, arkistot, lukija-prosessori-kirjoittaja-mallit, palaset, tarkistuspisteet, rinnakkaiskäsittely, virtaus, uusintayritykset, sekvensointi, partitioinnit jne.
Ymmärretäänpä arkkitehtuurin kulku.
- Työn arkisto (Job repository) sisältää suoritettavat työt (jobs).
-
JobLauncher
vetää työn (job) ulos työn arkistosta (Job repository). - Jokainen työ (job) sisältää vaiheita. Vaiheet ovat
ItemReader
,ItemProcessor
jaItemWriter
. - Item Reader on se, joka lukee tiedot.
- Item Process on se, joka käsittelee tiedot liiketoimintalogiikan perusteella.
- Itemin kirjoittaja kirjoittaa tiedot takaisin määriteltyyn lähteeseen.
1.3 Eräkäsittelyn komponentit.
Yritämme nyt ymmärtää eräkäsittelyn komponentteja yksityiskohtaisesti.
- Job: Työ käsittää koko eräprosessin. Se sisältää yhden tai useamman vaiheen. Työ kootaan käyttämällä Job Specification Language (JSL) -kieltä, jossa määritetään, missä järjestyksessä vaiheet on suoritettava. JSR 352:ssa JSL määritellään XML-tiedostossa, jota kutsutaan työn XML-tiedostoksi. Työ on periaatteessa säiliö, jossa on vaiheita.
- Step: Askel on toimialueen objekti, joka sisältää työn itsenäisen, peräkkäisen vaiheen. Askel sisältää kaiken tarvittavan logiikan ja datan varsinaisen käsittelyn suorittamiseksi. Askeleen määritelmä pidetään epämääräisenä erämäärittelyn mukaisesti, koska askeleen sisältö on puhtaasti sovelluskohtainen ja se voi olla niin monimutkainen tai yksinkertainen kuin kehittäjä haluaa. Askelia on kahdenlaisia: lohko- ja tehtäväsuuntautuneita.
- Job Operator: Se tarjoaa käyttöliittymän, jolla hallitaan kaikkia työnkäsittelyn osa-alueita, joihin kuuluvat operatiiviset komennot, kuten käynnistys, uudelleenkäynnistys ja pysäytys, sekä työn arkistokomennot, kuten työn ja askeleiden suoritusten haku.
- Job Repository: Se sisältää tietoja parhaillaan suoritettavista töistä ja historiatietoja töistä.
JobOperator
tarjoaa API:t tämän arkiston käyttämiseen.JobRepository
Voidaan toteuttaa käyttäen, tietokantaa tai tiedostojärjestelmää.
Seuraava jakso auttaa ymmärtämään eräarkkitehtuurin joitakin yleisiä merkkejä.
1.3 Työn vaiheet
Vaihe on työn itsenäinen vaihe. Kuten edellä käsiteltiin, Jobissa on kahdenlaisia vaiheita. Yritämme ymmärtää molempia tyyppejä yksityiskohtaisesti seuraavassa.
1.3.1 Palikkapainotteiset askeleet
Palikkapainotteiset askeleet lukevat ja käsittelevät yhden kohteen kerrallaan ja ryhmittelevät tulokset palikoiksi. Tulokset tallennetaan, kun kimpun koko on saavuttanut ennalta määritellyn koon. Kappalekohtainen käsittely tehostaa tulosten tallentamista, kun tietojoukko on suuri. Se sisältää kolme osaa.
- Elementinlukija lukee syötteen yksi kerrallaan tietolähteestä, joka voi olla tietokanta, tasotiedosto, lokitiedosto jne.
- Prosessori käsittelee tiedot yksi kerrallaan määritellyn liiketoimintalogiikan perusteella.
- Kirjoittaja kirjoittaa tiedot kappaleittain. Kappaleen koko on ennalta määritetty ja se on konfiguroitavissa
Kappaleiden vaiheissa on tarkistuspisteitä, jotka antavat kehykselle tietoa kappaleiden valmistumisesta. Jos kappalekäsittelyn aikana tapahtuu virhe, prosessi voidaan käynnistää uudelleen viimeisimmän tarkistuspisteen perusteella.
1.3.2 Tehtäväkeskeiset askeleet
Se suorittaa muita tehtäviä kuin tietolähteen kohteiden käsittelyä. Joka sisältää hakemistojen luomisen tai poistamisen, tiedostojen siirtämisen, tietokantataulujen luomisen tai poistamisen jne. Tehtäväkeskeiset vaiheet eivät yleensä ole pitkäkestoisia verrattuna kappalekohtaisiin vaiheisiin.
Normaalissa skenaariossa tehtäväkeskeisiä vaiheita käytetään kappalekohtaisten vaiheiden jälkeen, kun tarvitaan siivousta. Esimerkiksi sovelluksen tuloksena saadaan lokitiedostoja. Chunk-askeleita käytetään tietojen käsittelyyn ja lokitiedostoista saadaan mielekästä tietoa.
Tehtäväaskelia käytetään sen jälkeen vanhojen lokitiedostojen siivoamiseen, joita ei enää tarvita.
1.3.3 Rinnakkaiskäsittely
Batch-työt suorittavat usein kalliita laskentaoperaatioita ja käsittelevät suuria tietomääriä. Eräsovellukset voivat hyötyä rinnakkaiskäsittelystä kahdessa skenaariossa.
- Vaiheet, jotka ovat luonteeltaan riippumattomia, voidaan suorittaa eri säikeissä.
- Kokonaisuussuuntautuneet vaiheet, joissa kunkin kohteen käsittely on riippumaton edellisten kohteiden käsittelyn tuloksista, voidaan suorittaa useammassa kuin yhdessä säikeessä.
Sarjakäsittely auttaa saamaan tehtävät valmiiksi ja suorittamaan operaatiot nopeammin valtaville tiedoille.
Työkalut ja teknologiat
Katsotaanpa vielä ohjelman rakentamisessa käytettyjä teknologioita ja työkaluja.
- Eclipse Oxygen.2 Release (4.7.2)
- Java – versio 9.0.4
- Gradle- 4.3
- Spring boot – 2.0.1-Release
- HSQL-tietokanta
Projektin rakenne
Projektin rakenne näyttää alla olevan kuvan mukaisesti.
Projektirakenne Java Batchille
Yllä olevassa projektirakenteessa käytetään Gradlea. Tämä projekti voidaan luoda myös käyttämällä mavenia ja build.gralde korvataan pom.xml-tiedostolla. Projektin rakenne siirtyy hieman, kun käytetään Mavenia rakentamiseen.
Ohjelman tavoite
Ohjelman osana yritämme luoda yksinkertaisen java-eräajosovelluksen spring bootin avulla. Tämä sovellus suorittaa seuraavat tehtävät.
- Lue: – Lue työntekijätiedot CSV-tiedostosta.
- Käsittele tiedot: – Muunna työntekijätiedot suuraakkosiksi.
- Kirjoita: – Kirjoita käsitellyt työntekijätiedot takaisin tietokantaan.
4.1 Gradle build
Käytämme Gradlea rakentamiseen osana ohjelmaa. Tiedosto build.gradle
näyttää alla olevan kuvan mukaiselta.
build.gradle
buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE") }}apply plugin: 'java'apply plugin: 'eclipse'apply plugin: 'idea'apply plugin: 'org.springframework.boot'apply plugin: 'io.spring.dependency-management'bootJar { baseName = 'java-batch' version = '1.0'}repositories { mavenCentral()}sourceCompatibility = 1.8targetCompatibility = 1.8dependencies { compile("org.springframework.boot:spring-boot-starter-batch") compile("org.hsqldb:hsqldb") testCompile("junit:junit")}
Yllä olevassa build.gradle
tiedostossa apply plugin: 'java'
kertoo meille pluginin, joka pitää asettaa. Meille se on Java-lisäosa.repositories{}
kertoo arkiston, josta riippuvuus tulee vetää. Me olemme valinneet mavenCentral
vetääksemme riippuvuuspurkit. Voimme käyttää myös jcenter
vastaavien riippuvuuspurkkien vetämiseen.
dependencies {}
-tunnistetta käytetään tarvittavien jar-tiedostojen yksityiskohtien antamiseen, jotka pitäisi vetää projektia varten. apply plugin: 'org.springframework.boot'
tätä laajennusta käytetään spring-boot-projektin määrittämiseen. boot jar{}
määritetään sen jarin ominaisuudet, joka generoidaan buildista.
4.2 Esimerkkidatatiedosto
Lukuvaiheen tietojen antamiseksi käytämme CSV-tiedostoa, joka sisältää työntekijän tiedot.
Tiedosto näyttää alla esitetyltä.
Esimerkki-CSV-tiedosto
John,FosterJoe,ToyJustin,TaylorJane,ClarkJohn,Steve
Esimerkkidatatiedostossa on työntekijän etu- ja sukunimi. Käytämme samaa dataa käsittelyyn ja sen jälkeen tietokantaan lisäämiseen.
4.3 SQL-skriptit
Käytämme HSQL-tietokantaa, joka on muistipohjainen tietokanta. Skripti näyttää alla esitetyltä.
SQL-skripti
DROP TABLE employee IF EXISTS;CREATE TABLE employee ( person_id BIGINT IDENTITY NOT NULL PRIMARY KEY, first_name VARCHAR(20), last_name VARCHAR(20));
Spring Boot käynnistyy schema-@@platform@@.sql
automaattisesti, kun se käynnistyy. -all
on oletusarvo kaikilla alustoilla. Taulukon luominen tapahtuu siis itsestään, kun sovellus käynnistyy ja se on käytettävissä, kunnes sovellus on käynnissä.
4.4 Model Class
Luomme Employee.java
-luokan malliluokaksi. Luokka tulee näyttämään alla olevan kuvan mukaiselta.
Malliluokka ohjelmalle
package com.batch;public class Employee { private String lastName; private String firstName; public Employee() { } public Employee(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Override public String toString() { return "firstName: " + firstName + ", lastName: " + lastName; }}
@Override
käytetään toString()
-metodin toString()
oletustoteutuksen ohittamiseen.
4.5 Konfiguraatioluokka
Luomme BatchConfiguration.java
-luokan, joka on konfiguraatioluokka eräkäsittelylle. Java-tiedostosta tulee alla esitetyn näköinen.
BatchConfiguration.java
package com.batch.config;import javax.sql.DataSource;import org.springframework.batch.core.Job;import org.springframework.batch.core.JobExecutionListener;import org.springframework.batch.core.Step;import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;import org.springframework.batch.core.launch.support.RunIdIncrementer;import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;import org.springframework.batch.item.database.JdbcBatchItemWriter;import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;import org.springframework.batch.item.file.FlatFileItemReader;import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;import org.springframework.batch.item.file.mapping.DefaultLineMapper;import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.ClassPathResource;import org.springframework.jdbc.core.JdbcTemplate;import com.batch.Employee;import com.batch.processor.EmployeeItemProcessor;@Configuration@EnableBatchProcessingpublic class BatchConfiguration { @Autowired public JobBuilderFactory jobBuilderFactory; @Autowired public StepBuilderFactory stepBuilderFactory; // tag::readerwriterprocessor @Bean public FlatFileItemReader reader() { return new FlatFileItemReaderBuilder() .name("EmployeeItemReader") .resource(new ClassPathResource("sample-data.csv")) .delimited() .names(new String{"firstName", "lastName"}) .fieldSetMapper(new BeanWrapperFieldSetMapper() {{ setTargetType(Employee.class); }}) .build(); } @Bean public EmployeeItemProcessor processor() { return new EmployeeItemProcessor(); } @Bean public JdbcBatchItemWriter writer(DataSource dataSource) { return new JdbcBatchItemWriterBuilder() .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) .sql("INSERT INTO employee (first_name, last_name) VALUES (:firstName, :lastName)") .dataSource(dataSource) .build(); } // end::readerwriterprocessor // tag::jobstep @Bean public Job importUserJob(JobCompletionNotificationListener listener, Step step1) { return jobBuilderFactory.get("importUserJob") .incrementer(new RunIdIncrementer()) .listener(listener) .flow(step1) .end() .build(); } @Bean public Step step1(JdbcBatchItemWriter writer) { return stepBuilderFactory.get("step1") .<Employee, Employee> chunk(10) .reader(reader()) .processor(processor()) .writer(writer) .build(); } // end::jobstep}
@EnableBatchProcessing
annotaatiota käytetään eräkäsittelyn mahdollistamiseen.JobBuilderFactory
on tehdas, jota käytetään työn rakentamiseen.StepBuilderFactory
käytetään askeleen luomiseen.
Metodilla step1()
on ominaisuus chunk()
. Tätä ominaisuutta käytetään syötteen pilkkomiseen määriteltyyn kokoon. Meillä koko on 10.
4.6 Elementtiprosessori
Itemeprosessori on rajapinta, joka vastaa tietojen käsittelystä. Toteutamme rajapinnan EmployeeItemProcessor.java
. Java-luokka näyttää alla olevan kuvan mukaiselta.
EmployeeItemProcessor.java
package com.batch.processor;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.batch.item.ItemProcessor;import com.batch.Employee;public class EmployeeItemProcessor implements ItemProcessor<Employee, Employee> { private static final Logger log = LoggerFactory.getLogger(EmployeeItemProcessor.class); @Override public Employee process(Employee emp) throws Exception { final String firstName = emp.getFirstName().toUpperCase(); final String lastName = emp.getLastName().toUpperCase(); final Employee transformedEmployee = new Employee(firstName, lastName); log.info("Converting (" + emp + ") into (" + transformedEmployee + ")"); return transformedEmployee; }}
Metodissa process()
saamme datan ja muutamme sen isolla alkukirjaimella kirjoitetuksi nimeksi.
4.7 JobExecutionSupportListener-luokka
JobExecutionListenerSupport
on rajapinta, joka ilmoittaa, kun työ on valmis. Osana rajapintaa on afterJob
-metodi. Tätä metodia käytetään työn valmistumisesta ilmoittamiseen.
JobCompletionNotificationListener.java
package com.batch.config;import java.util.List;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.batch.core.BatchStatus;import org.springframework.batch.core.JobExecution;import org.springframework.batch.core.listener.JobExecutionListenerSupport;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import org.springframework.stereotype.Component;import com.batch.Employee;@Componentpublic class JobCompletionNotificationListener extends JobExecutionListenerSupport {private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);private final JdbcTemplate jdbcTemplate;@Autowiredpublic JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic void afterJob(JobExecution jobExecution) {RowMapper rowMapper = (rs, rowNum) -> {Employee e = new Employee();e.setFirstName(rs.getString(1));e.setLastName(rs.getString(2));return e;};if(jobExecution.getStatus() == BatchStatus.COMPLETED) {log.info("!!! JOB FINISHED! Time to verify the results");List empList= jdbcTemplate.query("SELECT first_name, last_name FROM employee",rowMapper);log.info("Size of List "+empList.size());for (Employee emp: empList) {log.info("Found: "+emp.getFirstName()+" "+emp.getLastName());}}}}
Tässä metodissa haemme tiedot tietokannasta työn valmistumisen jälkeen ja tulostamme tuloksen konsoliin todentaaksemme tietojen käsittelyn, joka suoritettiin.
4.8 Sovellusluokka
Luomme sovellusluokan, joka sisältää päämetodin, joka on vastuussa java-erätaajuuslaskentaohjelman käynnistämisestä. Luokasta tulee alla esitetyn näköinen.
Application.java
package com.batch;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application { public static void main(String args) throws Exception { SpringApplication.run(Application.class, args); }}
@SpringBootApplication
on annotaatio, jota käytetään ohjelman määrittelyyn spring boot -ohjelmaksi.
Output
Toteutetaan sovellus Java-sovelluksena. Saamme konsoliin seuraavan tulosteen.
JavaBatch-ohjelman tuloste
Batch-ohjelman työnkulku on hyvin selvästi nähtävissä tulosteessa. Job alkaa importUserJob
, jonka jälkeen alkaa askel-1:n suoritus, jossa luetut tiedot muunnetaan isoksi.
Vaiheen käsittelyn jälkeen näemme konsolissa isolla kirjoitetun tuloksen.
Yhteenveto
Tässä opetusohjelmassa opimme seuraavat asiat:
- JavaBatch sisältää Jobeja (työtehtäviä), jotka voivat sisältää useita vaiheita.
- Jokainen vaihe on yhdistelmä lukemista, käsittelyä ja kirjoittamista.
- Voidaan pilkkoa data erikokoiseksi käsittelyä varten.
7. Lataa Eclipse-projekti
Tämä oli tutoriaali JavaBatchista SpringBootilla.