Pengantar Spring Batch

1. Perkenalan

Dalam artikel ini kita akan fokus pada pengantar praktis yang berfokus pada kode untuk Spring Batch. Spring Batch adalah kerangka kerja pemrosesan yang dirancang untuk pelaksanaan pekerjaan yang tangguh.

Saat ini versi 3.0, yang mendukung Spring 4 dan Java 8. Ini juga mengakomodasi JSR-352, yang merupakan spesifikasi java baru untuk pemrosesan batch.

Berikut adalah beberapa kasus penggunaan framework yang menarik dan praktis.

2. Dasar-dasar Alur Kerja

Batch musim semi mengikuti arsitektur batch tradisional di mana repositori pekerjaan melakukan pekerjaan penjadwalan dan berinteraksi dengan pekerjaan.

Sebuah pekerjaan dapat memiliki lebih dari satu langkah - dan setiap langkah biasanya mengikuti urutan membaca data, memprosesnya, dan menulisnya.

Dan tentu saja kerangka kerja akan melakukan sebagian besar pekerjaan berat untuk kita di sini - terutama jika menyangkut pekerjaan ketekunan tingkat rendah dalam menangani pekerjaan - menggunakan sqlite untuk repositori pekerjaan.

2.1. Contoh Kami Usecase

Kasus penggunaan sederhana yang akan kami tangani di sini adalah - kami akan memindahkan beberapa data transaksi keuangan dari CSV ke XML.

File input memiliki struktur yang sangat sederhana - berisi transaksi per baris, terdiri dari: nama pengguna, id pengguna, tanggal transaksi, dan jumlahnya:

username, userid, transaction_date, transaction_amount devendra, 1234, 31/10/2015, 10000 john, 2134, 3/12/2015, 12321 robin, 2134, 2/02/2015, 23411

3. The Maven POM

Ketergantungan yang diperlukan untuk proyek ini adalah inti pegas, tumpukan pegas, dan konektor jdbc sqlite :

   org.xerial sqlite-jdbc 3.15.1   org.springframework spring-oxm 5.2.0.RELEASE   org.springframework spring-jdbc 5.2.0.RELEASE   org.springframework.batch spring-batch-core 4.2.0.RELEASE 

4. Konfigurasi Spring Batch

Hal pertama yang akan kita lakukan adalah mengonfigurasi Spring Batch dengan XML:

Tentu saja konfigurasi Java juga tersedia:

@Configuration @EnableBatchProcessing public class SpringConfig { @Value("org/springframework/batch/core/schema-drop-sqlite.sql") private Resource dropReopsitoryTables; @Value("org/springframework/batch/core/schema-sqlite.sql") private Resource dataReopsitorySchema; @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.sqlite.JDBC"); dataSource.setUrl("jdbc:sqlite:repository.sqlite"); return dataSource; } @Bean public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws MalformedURLException { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); databasePopulator.addScript(dropReopsitoryTables); databasePopulator.addScript(dataReopsitorySchema); databasePopulator.setIgnoreFailedDrops(true); DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); initializer.setDatabasePopulator(databasePopulator); return initializer; } private JobRepository getJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(dataSource()); factory.setTransactionManager(getTransactionManager()); factory.afterPropertiesSet(); return (JobRepository) factory.getObject(); } private PlatformTransactionManager getTransactionManager() { return new ResourcelessTransactionManager(); } public JobLauncher getJobLauncher() throws Exception { SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); jobLauncher.setJobRepository(getJobRepository()); jobLauncher.afterPropertiesSet(); return jobLauncher; } }

5. Konfigurasi Pekerjaan Spring Batch

Sekarang mari kita tulis deskripsi pekerjaan kita untuk pekerjaan CSV ke XML:

                           com.baeldung.spring_batch_intro.model.Transaction           

Dan tentu saja, konfigurasi pekerjaan berbasis Java yang serupa:

public class SpringBatchConfig { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Value("input/record.csv") private Resource inputCsv; @Value("file:xml/output.xml") private Resource outputXml; @Bean public ItemReader itemReader() throws UnexpectedInputException, ParseException { FlatFileItemReader reader = new FlatFileItemReader(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); String[] tokens = { "username", "userid", "transactiondate", "amount" }; tokenizer.setNames(tokens); reader.setResource(inputCsv); DefaultLineMapper lineMapper = new DefaultLineMapper(); lineMapper.setLineTokenizer(tokenizer); lineMapper.setFieldSetMapper(new RecordFieldSetMapper()); reader.setLineMapper(lineMapper); return reader; } @Bean public ItemProcessor itemProcessor() { return new CustomItemProcessor(); } @Bean public ItemWriter itemWriter(Marshaller marshaller) throws MalformedURLException { StaxEventItemWriter itemWriter = new StaxEventItemWriter(); itemWriter.setMarshaller(marshaller); itemWriter.setRootTagName("transactionRecord"); itemWriter.setResource(outputXml); return itemWriter; } @Bean public Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(new Class[] { Transaction.class }); return marshaller; } @Bean protected Step step1(ItemReader reader, ItemProcessor processor, ItemWriter writer) { return steps.get("step1"). chunk(10) .reader(reader).processor(processor).writer(writer).build(); } @Bean(name = "firstBatchJob") public Job job(@Qualifier("step1") Step step1) { return jobs.get("firstBatchJob").start(step1).build(); } }

Oke, jadi sekarang kita sudah memiliki seluruh konfigurasi, mari kita hancurkan dan mulai membahasnya.

5.1. Membaca Data dan Membuat Objek Dengan ItemReader

Pertama kita mengkonfigurasi cvsFileItemReader yang akan membaca data dari record.csv dan mengubahnya menjadi objek Transaction :

@SuppressWarnings("restriction") @XmlRootElement(name = "transactionRecord") public class Transaction { private String username; private int userId; private LocalDateTime transactionDate; private double amount; /* getters and setters for the attributes */ @Override public String toString() { return "Transaction [username=" + username + ", userId=" + userId + ", transactionDate=" + transactionDate + ", amount=" + amount + "]"; } }

Untuk melakukannya - ini menggunakan pembuat peta khusus:

public class RecordFieldSetMapper implements FieldSetMapper { public Transaction mapFieldSet(FieldSet fieldSet) throws BindException { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyy"); Transaction transaction = new Transaction(); transaction.setUsername(fieldSet.readString("username")); transaction.setUserId(fieldSet.readInt(1)); transaction.setAmount(fieldSet.readDouble(3)); String dateString = fieldSet.readString(2); transaction.setTransactionDate(LocalDate.parse(dateString, formatter).atStartOfDay()); return transaction; } }

5.2. Memproses Data Dengan ItemProcessor

Kami telah membuat prosesor item kami sendiri, CustomItemProcessor . Ini tidak memproses apa pun yang terkait dengan objek transaksi - yang dilakukannya hanyalah meneruskan objek asli yang berasal dari pembaca ke penulis:

public class CustomItemProcessor implements ItemProcessor { public Transaction process(Transaction item) { return item; } }

5.3. Writing Objects to the FS With ItemWriter

Finally, we are going to store this transaction into an xml file located at xml/output.xml:

5.4. Configuring the Batch Job

So all we have to do is connect the dots with a job – using the batch:job syntax.

Note the commit-interval – that's the number of transactions to be kept in memory before committing the batch to the itemWriter; it will hold the transactions in memory until that point (or until the end of the input data is encountered):

5.5. Running the Batch Job

That's it – let's now set up and run everything:

public class App { public static void main(String[] args) { // Spring Java config AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(SpringConfig.class); context.register(SpringBatchConfig.class); context.refresh(); JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); Job job = (Job) context.getBean("firstBatchJob"); System.out.println("Starting the batch job"); try { JobExecution execution = jobLauncher.run(job, new JobParameters()); System.out.println("Job Status : " + execution.getStatus()); System.out.println("Job completed"); } catch (Exception e) { e.printStackTrace(); System.out.println("Job failed"); } } }

6. Conclusion

Tutorial ini memberi Anda ide dasar tentang cara bekerja dengan Spring Batch dan cara menggunakannya dalam kasus penggunaan sederhana.

Ini menunjukkan bagaimana Anda dapat dengan mudah mengembangkan pipeline pemrosesan batch Anda dan bagaimana Anda dapat menyesuaikan berbagai tahapan dalam membaca, memproses, dan menulis.

The implementasi penuh dari tutorial ini dapat ditemukan dalam proyek github - ini adalah proyek berbasis Eclipse, sehingga harus mudah untuk impor dan berjalan seperti itu.