Spring Batch এ Step হলো একটি ব্যাচ জবের একটি গুরুত্বপূর্ণ অংশ যা ডাটা প্রক্রিয়া করার জন্য নির্দিষ্ট একটি কাজ সম্পাদন করে। এক বা একাধিক স্টেপের সমন্বয়ে একটি ব্যাচ জব গঠিত হয়। প্রতিটি Step নির্দিষ্ট ইনপুট, প্রসেসিং এবং আউটপুট করার জন্য কনফিগার করা হয়। Step Configuration এ আপনি ItemReader, ItemProcessor, এবং ItemWriter এর মধ্যে সম্পর্ক স্থাপন করেন, যা ডাটা রিড, প্রসেস, এবং লেখার জন্য ব্যবহৃত হয়।
Spring Batch এ Step Configuration হল ব্যাচ প্রক্রিয়া কনফিগার করার অন্যতম গুরুত্বপূর্ণ অংশ। এখানে ব্যাচ প্রক্রিয়ার কাজ সম্পন্ন করার জন্য আপনাকে Step কনফিগার করতে হয় এবং একটি ব্যাচ জব তৈরির সময় একাধিক Step যোগ করা যায়।
Step Configuration Overview
Spring Batch Step Configuration এর মধ্যে নিম্নলিখিত উপাদানগুলির কনফিগারেশন করা হয়:
- ItemReader: ডাটাবেস, ফাইল বা অন্য কোনো উৎস থেকে ডাটা পড়া।
- ItemProcessor: ডাটা প্রসেসিং (যেমন ডাটা ফিল্টারিং, কনভার্সন বা অন্যান্য লজিক)।
- ItemWriter: প্রসেস করা ডাটা সংরক্ষণ বা রিটেন করা (ডাটাবেস, ফাইল ইত্যাদিতে লেখা)।
- Chunk Size: কতগুলো আইটেম একসাথে প্রক্রিয়া হবে সেটি নির্ধারণ করা (চাঙ্ক ভিত্তিক প্রক্রিয়া)।
Step Configuration উদাহরণ
Spring Batch Step কনফিগারেশন সঠিকভাবে তৈরি করতে নিচে একটি উদাহরণ দেওয়া হয়েছে যেখানে ItemReader, ItemProcessor, এবং ItemWriter কনফিগার করা হয়েছে।
1. Step কনফিগারেশন ক্লাস তৈরি করা
package com.example.demo;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BatchConfig {
@Bean
public Job job(JobBuilderFactory jobBuilderFactory, Step step1) {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.flow(step1) // Step configuration
.end()
.build();
}
@Bean
public Step step1(StepBuilderFactory stepBuilderFactory,
ItemReader<String> reader,
ItemProcessor<String, String> processor,
ItemWriter<String> writer) {
return stepBuilderFactory.get("step1")
.<String, String>chunk(10) // chunk size set to 10
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
// ItemReader, ItemProcessor, and ItemWriter beans will be configured below
}
এখানে, StepBuilderFactory এর মাধ্যমে Step কনফিগার করা হয়েছে এবং chunk(10) এর মাধ্যমে প্রতিটি চাঙ্কে ১০টি আইটেম প্রক্রিয়া হবে সেটি নির্ধারণ করা হয়েছে।
2. ItemReader, ItemProcessor, and ItemWriter তৈরি করা
ItemReader, ItemProcessor, এবং ItemWriter তৈরি করা হয় যেগুলি ডাটা রিড, প্রসেস এবং লেখার জন্য ব্যবহৃত হবে।
- ItemReader: ডাটাবেস, ফাইল বা অন্য কোনো উৎস থেকে ডাটা পড়বে।
- ItemProcessor: পড়া ডাটা প্রসেস করবে (যেমন ডাটা ফিল্টারিং বা কনভার্সন)।
- ItemWriter: প্রসেস করা ডাটাকে কোনো আউটপুট উৎসে লিখবে (যেমন ডাটাবেস, ফাইল ইত্যাদি)।
package com.example.demo;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemWriter;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class SimpleReader implements ItemReader<String> {
private int count = 0;
private final String[] data = {"Item1", "Item2", "Item3", "Item4", "Item5"};
@Override
public String read() throws Exception {
if (count < data.length) {
return data[count++];
}
return null; // End of data
}
}
@Component
public class SimpleProcessor implements ItemProcessor<String, String> {
@Override
public String process(String item) throws Exception {
return item.toUpperCase(); // Convert item to uppercase
}
}
@Component
public class SimpleWriter implements ItemWriter<String> {
@Override
public void write(List<? extends String> items) throws Exception {
items.forEach(System.out::println); // Write each item to console
}
}
এখানে, SimpleReader ক্লাসে read() মেথড ব্যবহার করে ডাটাবেস বা ফাইল থেকে ডাটা পড়া হচ্ছে। SimpleProcessor ডাটাকে uppercase করে এবং SimpleWriter ডাটাকে কনসোলে লিখছে।
3. JobLauncher দিয়ে ব্যাচ জব রান করা
Spring Batch এর JobLauncher ব্যবহার করে ব্যাচ জব রান করা হয়। এই জবটি চালানোর জন্য CommandLineRunner অথবা অন্য কোনো Trigger ব্যবহার করা যেতে পারে।
package com.example.demo;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class JobRunner implements CommandLineRunner {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Override
public void run(String... args) throws Exception {
jobLauncher.run(job, new JobParameters());
}
}
এখানে JobLauncher ব্যাচ জব চালানোর জন্য ব্যবহৃত হচ্ছে এবং run() মেথডের মাধ্যমে এই জবটি চালানো হচ্ছে।
Step কনফিগারেশন এর সুবিধা
- Chunk-based processing: Step কনফিগারেশন দ্বারা আপনি চাঙ্ক-বেসড প্রসেসিং পরিচালনা করতে পারেন, যেখানে একটি বড় ডাটাবেস বা ফাইলের ডাটা ছোট ছোট অংশে প্রক্রিয়া করা হয়। এতে সিস্টেম রিসোর্স ব্যবহারের দক্ষতা বৃদ্ধি পায়।
- Decoupling: Step গুলো পৃথক পৃথকভাবে কনফিগার করা হয়, যা প্রোগ্রামটির মডুলারিটি এবং রিইউজেবিলিটি বৃদ্ধি করে।
- Error handling: Step-এর মধ্যে error handling এবং ট্রানজেকশন ম্যানেজমেন্ট সহজ করা হয়, যাতে ডাটা সঠিকভাবে প্রক্রিয়া এবং সংরক্ষণ করা যায়।
- Parallel Execution: Multiple steps can be executed in parallel or sequentially, depending on the requirements.
সারাংশ
Spring Batch এ Step Configuration একটি গুরুত্বপূর্ণ অংশ, যা ডাটা রিড, প্রসেস এবং লেখার জন্য ব্যবহৃত হয়। ItemReader, ItemProcessor, এবং ItemWriter ব্যবহার করে Step কনফিগার করা হয়, এবং chunk-based processing এর মাধ্যমে একসাথে একাধিক ডাটা প্রক্রিয়া করা হয়। Spring Batch এর Step কনফিগারেশন ডাটা প্রক্রিয়ার গতি বৃদ্ধি, রিসোর্স ব্যবস্থাপনা এবং অ্যাপ্লিকেশনের স্কেলেবিলিটি উন্নত করতে সাহায্য করে।
Spring Batch একটি শক্তিশালী ফ্রেমওয়ার্ক যা বড় পরিমাণে ডেটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়। এটি বিশেষ করে ব্যাচ প্রসেসিংয়ের জন্য ডিজাইন করা হয়েছে, যেখানে আপনি একটি সিরিজের কাজ বা কাজের ধাপ (steps) সম্পন্ন করার মাধ্যমে বড় কাজগুলো সম্পাদন করেন। Spring Batch-এ Step একটি অত্যন্ত গুরুত্বপূর্ণ উপাদান, কারণ এটি ব্যাচ প্রসেসিংয়ের একটি মৌলিক ইউনিট।
Step কি?
Spring Batch-এ Step হল একটি একক কাজ যা একটি ব্যাচ জব (Job) এর অংশ হিসেবে পরিচালিত হয়। প্রতিটি Step ডেটা রিড, প্রসেস এবং রাইটের মতো নির্দিষ্ট কাজ সম্পাদন করে। Step একটি নির্দিষ্ট কাজ বা প্রক্রিয়ার অংশ, যা পুরো ব্যাচ জবের কার্যক্রমে অবদান রাখে। Step গুলি সিরিয়ালি বা প্যারালালি একে অপরের পর পর সম্পন্ন হতে পারে।
প্রতিটি Step একটি নির্দিষ্ট কার্যকলাপ (যেমন: ডেটা রিড করা, প্রক্রিয়া করা, অথবা ডেটা রাইট করা) সম্পাদন করে এবং এটি সফলভাবে বা ব্যর্থভাবে শেষ হতে পারে। যখন Step সফলভাবে সম্পন্ন হয়, তখন এটি পরবর্তী Step বা শেষ জবের ফলাফল তৈরি করতে সাহায্য করে।
Step এর গঠন
Spring Batch-এ একটি Step মূলত তিনটি উপাদান দিয়ে গঠিত:
- ItemReader: এটি ডেটা রিড করার জন্য ব্যবহৃত হয়।
- ItemProcessor: এটি রিড করা ডেটার উপর প্রক্রিয়া বা কাস্টম লজিক প্রয়োগ করে।
- ItemWriter: এটি প্রক্রিয়া করা ডেটা কোথাও (যেমন ডেটাবেস, ফাইল, বা অন্য কোনো স্টোরেজে) রাইট করে।
এগুলি একত্রে একটি Chunk Processing প্যাটার্নে কাজ করে, যেখানে ডেটা ছোট অংশে প্রক্রিয়া করা হয় এবং প্রতিটি অংশ শেষে রাইট করা হয়।
Step এর উদাহরণ:
@Bean
public Job job(JobCompletionNotificationListener listener, Step step1) {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.listener(listener)
.start(step1) // Step 1 কে চালু করে
.build();
}
@Bean
public Step step1(ItemReader<MyItem> reader, ItemProcessor<MyItem, MyProcessedItem> processor, ItemWriter<MyProcessedItem> writer) {
return stepBuilderFactory.get("step1")
.<MyItem, MyProcessedItem>chunk(10) // Chunk size 10
.reader(reader) // ডেটা রিড করতে
.processor(processor) // ডেটা প্রসেস করতে
.writer(writer) // প্রক্রিয়া করা ডেটা রাইট করতে
.build();
}
এখানে, step1 হল একটি Step, যা ItemReader, ItemProcessor, এবং ItemWriter ব্যবহার করে ডেটা প্রক্রিয়াকরণের জন্য একটি chunk প্রক্রিয়া পরিচালনা করছে।
Step কেন গুরুত্বপূর্ণ?
1. ব্যাচ প্রসেসিংয়ের মৌলিক ইউনিট
Spring Batch-এ Step ব্যাচ প্রসেসিংয়ের মৌলিক ইউনিট। একটি Job তৈরি করতে কমপক্ষে একটি Step প্রয়োজন, এবং প্রতিটি Step ব্যাচ প্রক্রিয়ার একটি নির্দিষ্ট অংশে কাজ করে। একটি Job সাধারণত একাধিক Step নিয়ে গঠিত হয়, এবং প্রতিটি Step আলাদা আলাদা কাজ করে (যেমন ডেটা রিড করা, প্রসেস করা এবং রাইট করা)।
2. ডেটা প্রক্রিয়াকরণে নমনীয়তা
Spring Batch-এ Step ব্যবহারের মাধ্যমে আপনি ব্যাচ প্রসেসিংয়ে আলাদা আলাদা কাজের জন্য পৃথক কাস্টম লজিক প্রয়োগ করতে পারেন। প্রতিটি Step নির্দিষ্টভাবে আলাদা কাজ করে এবং এটি সফলভাবে বা ব্যর্থভাবে সম্পন্ন হতে পারে। এটি ব্যাচ প্রসেসিংয়ের উন্নত নিয়ন্ত্রণ এবং কাস্টমাইজেশন প্রদান করে।
- উদাহরণ: আপনি একটি Step দিয়ে ডেটা ফাইল থেকে পড়তে পারেন এবং অন্য একটি Step দিয়ে সেই ডেটা প্রক্রিয়া করে ডেটাবেসে লিখতে পারেন।
3. ভুল হওয়ার ক্ষেত্রে পুনঃপ্রচেষ্টা (Retry) এবং ত্রুটি পরিচালনা (Error Handling)
প্রতিটি Step ব্যাচ প্রসেসিংয়ের একটি আলাদা অংশ হওয়ায়, আপনি Step-এর জন্য পৃথকভাবে ত্রুটি পরিচালনা এবং পুনঃপ্রচেষ্টার কৌশল প্রয়োগ করতে পারেন। যদি একটি Step কোনো কারণে ব্যর্থ হয়, তবে আপনি শুধুমাত্র সেই Step পুনরায় চালাতে পারেন এবং পুরো Job পুনরায় চালানোর দরকার নেই।
- উদাহরণ: যদি ডেটা রাইটিং প্রক্রিয়ায় কোনো ত্রুটি ঘটে, আপনি শুধু রাইটিং Step পুনরায় চালাতে পারেন, কিন্তু পূর্ববর্তী Steps চালানোর দরকার নেই।
4. পারফরম্যান্স এবং স্কেলেবিলিটি
Step ব্যবহারের মাধ্যমে, আপনি প্রতিটি ধাপের জন্য আলাদা আলাদা কনফিগারেশন এবং পারফরম্যান্স টিউনিং করতে পারেন। আপনি Chunk Processing ব্যবহার করে ডেটা ছোট অংশে প্রক্রিয়া করতে পারেন, যা পারফরম্যান্স উন্নত করে এবং মেমরি ব্যবস্থাপনা সহজ করে।
- উদাহরণ: আপনি যদি একটি বিশাল ডেটাসেট প্রক্রিয়া করেন, তবে Step-এর মধ্যে
chunkব্যবহার করে তা ছোট ছোট অংশে প্রক্রিয়া করা যাবে, যা পুরো প্রক্রিয়াকে অনেক দ্রুত এবং কার্যকরী করে।
5. লজিকাল ডিভিশন এবং কোড রিইউজেবিলিটি
Step ব্যবহারের মাধ্যমে আপনি আপনার ব্যাচ জবের কার্যক্রমগুলিকে লজিক্যালি বিভক্ত করতে পারেন। এটি কোড রিইউজেবিলিটি বৃদ্ধি করে এবং নির্দিষ্ট কাজের জন্য আলাদা আলাদা Step তৈরি করা সহজ হয়।
- উদাহরণ: একটি জব তৈরি করতে, আপনি একটি Step ব্যবহার করে ডেটা রিড করবেন, অন্য Step দিয়ে ডেটা প্রসেস করবেন এবং আরেকটি Step দিয়ে ডেটা রাইট করবেন। এতে একাধিক কাজকে আলাদা আলাদা Step-এ ভাগ করা যায়, যা কোডের সুসংগতি বজায় রাখে।
Step এবং Chunk Processing
Spring Batch-এ Chunk Processing একটি গুরুত্বপূর্ণ কনসেপ্ট। এটি একটি প্রক্রিয়া প্যাটার্ন যেখানে ডেটা ছোট ছোট অংশে (chunks) প্রক্রিয়া করা হয়। প্রতিটি Step একটি chunk প্রক্রিয়া করে, যেখানে নির্দিষ্ট সংখ্যক আইটেম একসাথে পড়া, প্রক্রিয়া করা এবং লেখা হয়। এটি মেমরি ব্যবস্থাপনা এবং পারফরম্যান্স উন্নত করতে সহায়তা করে।
@Bean
public Step step1(ItemReader<MyItem> reader, ItemProcessor<MyItem, MyProcessedItem> processor, ItemWriter<MyProcessedItem> writer) {
return stepBuilderFactory.get("step1")
.<MyItem, MyProcessedItem> chunk(10) // Chunk size 10
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
এখানে chunk(10) নির্ধারণ করছে যে, প্রতি 10টি আইটেম একত্রে পড়া, প্রক্রিয়া করা এবং লেখা হবে।
সারাংশ
Spring Batch-এ Step হল একটি ব্যাচ জবের মূল উপাদান, যা একটি নির্দিষ্ট কাজ বা কার্যকলাপ সম্পন্ন করে। Step এর মধ্যে ItemReader, ItemProcessor, এবং ItemWriter অন্তর্ভুক্ত থাকে যা ডেটা রিড, প্রসেস এবং রাইট করার জন্য ব্যবহৃত হয়। Step ব্যবহারের মাধ্যমে আপনি ব্যাচ প্রক্রিয়াকে ছোট ছোট ইউনিটে বিভক্ত করতে পারেন, যা কোডের রিইউজেবিলিটি, পারফরম্যান্স এবং ত্রুটি পরিচালনাকে সহজ করে তোলে। Spring Batch-এ Step-এর মাধ্যমে আপনি ডেটা প্রক্রিয়াকরণের কার্যক্রমকে আরও নিয়ন্ত্রিত এবং স্কেলেবল করতে পারেন।
স্প্রিং ব্যাচ (Spring Batch) একটি ফ্রেমওয়ার্ক যা বড় পরিসরের ব্যাচ প্রসেসিং-এর জন্য ডিজাইন করা হয়েছে। এটি মূলত জাভা টেকনোলজি ব্যবহার করে ডেটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়। স্প্রিং ব্যাচের মধ্যে দুটি মূল উপাদান আছে যেগুলোর মাধ্যমে ব্যাচ প্রসেসিং পরিচালিত হয়: Chunk-based এবং Tasklet-based Step। এই দুইটি ভিত্তিক Step-এর কাজগুলো বিস্তারিতভাবে জানবো।
Chunk-based Step
Chunk-based Step হলো একটি স্টেপ যেখানে ডেটা ছোট ছোট অংশে (chunk) ভাগ করা হয় এবং প্রতিটি অংশের উপর আলাদা করে প্রসেসিং করা হয়। এটি তখনই উপকারী হয় যখন আপনি খুব বড় পরিসরের ডেটা নিয়ে কাজ করছেন এবং একে একে সব ডেটা মেমোরিতে লোড করা সম্ভব নয়।
কাজের প্রক্রিয়া:
- ItemReader: ডেটা পড়ার জন্য ব্যবহার করা হয়।
- ItemProcessor: প্রতিটি আইটেমের উপর প্রক্রিয়াকরণ করা হয়।
- ItemWriter: প্রক্রিয়াকৃত ডেটা কোন ডেস্টিনেশনে লেখার জন্য ব্যবহৃত হয়।
- CommitInterval: Chunk size হিসেবে ডেটার কত অংশ একসাথে প্রসেস করা হবে তা নির্ধারণ করে।
এতে করে প্রতি chunk এর শেষে commit করা হয়, অর্থাৎ প্রতি chunk প্রসেসিং শেষে ডেটা ডাটাবেসে সেভ হয়ে যায়।
Tasklet-based Step
Tasklet-based Step একটি সাধারাণ স্টেপ যেখানে একটি নির্দিষ্ট কাজ সম্পন্ন করার জন্য শুধুমাত্র একটির বেশি কার্যক্রম বা স্টেপের প্রয়োজন হয় না। Tasklet হল একটি সিঙ্গল টাস্ক যা ব্যাচ প্রসেসিংয়ের জন্য বিশেষভাবে উপযুক্ত, যেমন কোনও সিস্টেম বা ফাইল থেকে ডেটা সরানো, বা ডেটাবেসের মধ্যে নির্দিষ্ট আপডেট করা।
কাজের প্রক্রিয়া:
- Tasklet: এই স্টেপের মধ্যে আপনি একটি একক কার্যকলাপ সম্পন্ন করেন, যা একটি নির্দিষ্ট কাজের উপর ভিত্তি করে। Tasklet সাধারণত একটি
execute()মেথডের মাধ্যমে কাজ করে যা যে কাজটি করবে তা নির্দেশ করে।
উদাহরণ:
ফাইল সিস্টেম থেকে একটি ফাইল মুছে ফেলতে Tasklet-based Step ব্যবহার করা যেতে পারে।
প্রতিটি Step-ই নির্দিষ্ট পরিস্থিতিতে উপকারী। Chunk-based Step তখন ব্যবহৃত হয় যখন বড় পরিসরের ডেটা প্রসেস করতে হয় এবং Tasklet-based Step ব্যবহৃত হয় যখন একটি নির্দিষ্ট একক কাজ সম্পাদন করা প্রয়োজন।
স্প্রিং ব্যাচে Chunk-based এবং Tasklet-based Step-এ কাজ করার জন্য প্রাথমিকভাবে স্প্রিং ব্যাচের কিছু প্রয়োজনীয় কনফিগারেশন তৈরি করতে হয়। নিচে বিস্তারিত কোড সহ দুইটি ধরণের Step-এর উদাহরণ দেওয়া হলো।
Chunk-based Step এর উদাহরণ
Chunk-based প্রসেসিং-এ আপনি ডেটা পঠন, প্রক্রিয়া, এবং লেখার জন্য আলাদা আলাদা অংশ তৈরি করবেন। এখানে ItemReader, ItemProcessor, এবং ItemWriter ব্যবহার করা হয়।
প্রয়োজনীয় ডিপেনডেন্সি
স্প্রিং ব্যাচ ব্যবহার করতে হলে, pom.xml ফাইলে নিচের ডিপেনডেন্সি গুলি যুক্ত করতে হবে:
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>5.0.0</version> <!-- Ensure to use the latest version -->
</dependency>
কোড উদাহরণ
1. ItemReader, ItemProcessor, এবং ItemWriter ক্লাস তৈরি
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.stereotype.Component;
@Component
public class MyItemProcessor implements ItemProcessor<MyData, MyData> {
@Override
public MyData process(MyData item) throws Exception {
// Process each item (e.g., transforming it)
item.setName(item.getName().toUpperCase());
return item;
}
}
@Component
public class MyItemReader implements ItemReader<MyData> {
private List<MyData> data = Arrays.asList(
new MyData("John"), new MyData("Jane"), new MyData("Doe")
);
private int index = 0;
@Override
public MyData read() throws Exception {
if (index < data.size()) {
return data.get(index++);
}
return null; // End of data
}
}
@Component
public class MyItemWriter implements ItemWriter<MyData> {
@Override
public void write(List<? extends MyData> items) throws Exception {
for (MyData item : items) {
System.out.println("Writing: " + item.getName());
}
}
}
2. Chunk-based Step কনফিগারেশন
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.core.repository.JobRepository;
import org.springframework.batch.core.step.tasklet.TaskletStep;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.batch.core.Job;
@Configuration
@EnableBatchProcessing
public class BatchConfig {
@Bean
public Job job(JobBuilderFactory jobBuilderFactory, Step step) {
return jobBuilderFactory.get("myJob")
.incrementer(new RunIdIncrementer())
.start(step)
.build();
}
@Bean
public Step step(StepBuilderFactory stepBuilderFactory, MyItemReader reader, MyItemProcessor processor, MyItemWriter writer) {
return stepBuilderFactory.get("myStep")
.<MyData, MyData>chunk(2) // 2 items per chunk
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
}
3. MyData ক্লাস
public class MyData {
private String name;
public MyData(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
এই কনফিগারেশন অনুসারে, ২টি ডেটা একসাথে প্রসেস করা হবে প্রতি চাঙ্কে এবং প্রতিটি আইটেম প্রসেস করার পরে ItemWriter তাদের আউটপুট দেখাবে।
Tasklet-based Step এর উদাহরণ
Tasklet-based Step-এ আপনি একক কার্যক্রম সম্পাদন করেন। উদাহরণস্বরূপ, একটি ফাইল থেকে ডেটা সরিয়ে ফেলা বা নির্দিষ্ট কোনও কাজ করতে এই পদ্ধতি ব্যবহার করা হয়।
কোড উদাহরণ
1. Tasklet কনফিগারেশন
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.core.repository.JobRepository;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.batch.core.Job;
@Configuration
@EnableBatchProcessing
public class TaskletBatchConfig {
@Bean
public Job taskletJob(JobBuilderFactory jobBuilderFactory, Step taskletStep) {
return jobBuilderFactory.get("taskletJob")
.incrementer(new RunIdIncrementer())
.start(taskletStep)
.build();
}
@Bean
public Step taskletStep(StepBuilderFactory stepBuilderFactory, Tasklet myTasklet) {
return stepBuilderFactory.get("taskletStep")
.tasklet(myTasklet)
.build();
}
@Bean
public Tasklet myTasklet() {
return (contribution, chunkContext) -> {
System.out.println("Executing Tasklet...");
return null; // return null to indicate completion
};
}
}
2. Tasklet ব্যবহার করে কোনো কাজ
এখানে Tasklet একটি নির্দিষ্ট কাজ সম্পাদন করছে, যেমন কনসোল আউটপুট। আপনি আরও জটিল কাজ যেমন ফাইল রিড, ডাটাবেস অপারেশন বা ফাইল মুছে ফেলা ইত্যাদি করতে পারেন।
এই দুইটি উদাহরণের মাধ্যমে আপনি স্প্রিং ব্যাচের Chunk-based এবং Tasklet-based Step এর কনফিগারেশন এবং কাজ দেখতে পেলেন। আপনার প্রজেক্টের প্রয়োজন অনুযায়ী এগুলো ব্যবহার করতে পারেন।
Spring Batch একটি শক্তিশালী ফ্রেমওয়ার্ক যা ব্যাচ প্রসেসিংয়ের জন্য ব্যবহৃত হয়, যেমন বড় ডেটাসেটের প্রক্রিয়াকরণ, ডেটা ট্রান্সফরমেশন, এবং ডেটা মাইগ্রেশন। Spring Batch এর একটি গুরুত্বপূর্ণ উপাদান হলো Step, যা একটি নির্দিষ্ট ব্যাচ কাজ সম্পাদন করে। Step দুটি প্রধান ধরনের হতে পারে: Chunk-based এবং Tasklet-based।
এই দুইটি ধরনের Step এর কাজ আলাদা, এবং এগুলির মাধ্যমে ডেটা প্রসেসিংয়ের বিভিন্ন শৈলী ব্যবহার করা যায়।
Chunk-based Step
Chunk-based Step হলো এমন একটি প্রসেসিং মডেল যেখানে ডেটাকে ছোট ছোট অংশ (chunk) এ বিভক্ত করে একাধিক রেকর্ড একসঙ্গে প্রসেস করা হয়। একটি chunk-এ অনেকগুলো আইটেম হতে পারে, এবং প্রতিটি chunk প্রসেস করার পর, সেই chunk এর জন্য একত্রিত হয়ে একটি কমিট (commit) করা হয়।
Chunk-based Step এর কাজ:
- ItemReader: এটি ডেটা রিড করে (যেমন, ডাটাবেস থেকে, ফাইল থেকে বা অন্য কোনো সোর্স থেকে)। এটি একে একে ডেটার আইটেম পাঠায়।
- ItemProcessor: এই স্টেপে ডেটার আইটেমগুলোর উপর প্রক্রিয়া বা ট্রান্সফরমেশন (transformation) করা হয়। এটি একটি আইটেমকে গ্রহণ করে এবং তাকে কোনোভাবে পরিবর্তন করে।
- ItemWriter: প্রসেস হওয়া আইটেমগুলোকে ডাটাবেসে, ফাইলে বা অন্য কোনো টার্গেট আউটপুটে লিখে দেয়।
- Committer: প্রতিটি chunk প্রসেস হওয়ার পরে,
ItemWriterদিয়ে ডেটা কমিট করা হয়। অর্থাৎ, chunk এর সমস্ত আইটেম একত্রে প্রক্রিয়াকৃত হয়ে আউটপুটে লেখা হয়।
Chunk-based Step উদাহরণ:
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10) // প্রতি 10টি আইটেমের পরে কমিট হবে
.reader(personReader())
.processor(personProcessor())
.writer(personWriter())
.build();
}
@Bean
public ItemReader<Person> personReader() {
return new PersonItemReader(); // ডেটা রিডারের উদাহরণ
}
@Bean
public ItemProcessor<Person, Person> personProcessor() {
return new PersonItemProcessor(); // ডেটা প্রসেসরের উদাহরণ
}
@Bean
public ItemWriter<Person> personWriter() {
return new PersonItemWriter(); // ডেটা রাইটারের উদাহরণ
}
এখানে, chunk(10) নির্দেশ করে যে প্রতি 10টি আইটেম প্রসেস হওয়ার পর কমিট করা হবে। এটি ItemReader, ItemProcessor, এবং ItemWriter সমন্বয়ে কাজ করে।
Chunk-based Step এর সুবিধা:
- Batch Size Control: একযোগভাবে অনেক আইটেম প্রসেস করা হয়, ফলে মেমরি ব্যবহারের পরিমাণ নিয়ন্ত্রণ করা যায়।
- Transaction Management: প্রতিটি chunk আলাদা আলাদা ট্রানজেকশনে প্রক্রিয়াকৃত হয়, যা ডেটা কমিট করতে সাহায্য করে।
- Error Handling: একটি chunk এর মধ্যে কোনো সমস্যা হলে, সেই chunk পুনরায় প্রসেস করা যায়।
Tasklet-based Step
Tasklet-based Step হলো এমন একটি প্রসেসিং মডেল যেখানে একটি নির্দিষ্ট কাজ (task) একবারে সম্পন্ন করা হয়। এখানে ডেটার chunk ভাগ করা হয় না, বরং একটি নির্দিষ্ট কাজ একটি স্টেপে সম্পন্ন হয়, যেমন ডেটাবেস টেবিল ক্লিয়ার করা, ফাইল মুছে ফেলা বা কোনো নির্দিষ্ট স্ট্যাটাস আপডেট করা। Tasklet একটি প্রক্রিয়া বা কাজের উপর দৃষ্টি নিবদ্ধ করে, যা সাধারণত Void ধরনের কাজ হয়।
Tasklet-based Step এর কাজ:
- Tasklet: এটি সাধারণত একটি নির্দিষ্ট কাজের কার্যক্রম সম্পাদন করে, যেমন ডেটাবেস টেবিল মুছে ফেলা বা রিপোর্ট তৈরি করা। Tasklet একটি নির্দিষ্ট কাজ করার জন্য তৈরি করা হয়, এবং এটি শুধুমাত্র একটি স্টেপে একবার রান হয়।
- ExecutionContext: Tasklet স্টেপে কাজ করার সময়,
ExecutionContextব্যবহার করে আপনি স্টেপের মধ্যে স্টেট সংরক্ষণ করতে পারেন, যা পরবর্তী রানগুলোর জন্য দরকারি হতে পারে।
Tasklet-based Step উদাহরণ:
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Tasklet is executing");
return RepeatStatus.FINISHED; // কাজ সম্পন্ন হলে।
}
})
.build();
}
এখানে একটি Tasklet তৈরি করা হয়েছে যা একটি কাজ সম্পাদন করবে, যেমন কনসোল এ "Tasklet is executing" মেসেজ প্রিন্ট করবে।
Tasklet-based Step এর সুবিধা:
- Simple Tasks: ছোট, সহজ এবং একক কাজের জন্য উপযোগী।
- Flexibility: Tasklet দিয়ে একক কাজ যেমন রিপোর্ট জেনারেশন, ফাইল অপারেশন বা ক্লিনআপ কাজ করতে পারেন।
- No Chunking: Tasklet কোনো chunk বা ব্যাচ প্রসেসিংয়ের সাথে সম্পর্কিত নয়। এটি একক কাজ হিসেবেই কাজ করে।
Chunk এবং Tasklet ভিত্তিক Step এর তুলনা
| Feature | Chunk-based Step | Tasklet-based Step |
|---|---|---|
| Data Processing | ডেটার আইটেমগুলো chunk আকারে প্রসেস করা হয়। | একক কাজ (task) হিসাবে একবারেই কাজ করা হয়। |
| Use Case | বড় আকারের ডেটা প্রসেসিং (যেমন ডেটাবেস থেকে তথ্য সংগ্রহ করা)। | ছোট কাজ, যেমন ক্লিনআপ বা রিপোর্ট তৈরি। |
| Error Handling | Chunk প্রক্রিয়াকরণের মধ্যে ত্রুটি ঘটলে পুরো chunk পুনরায় প্রসেস করা যায়। | কোনো ত্রুটি হলে পুরো task পুনরায় চেষ্টা করা যায়। |
| Transaction Management | প্রতিটি chunk আলাদা আলাদা ট্রানজেকশনে সম্পাদিত হয়। | একটি ট্রানজেকশনে সম্পূর্ণ task সম্পন্ন হয়। |
| Complexity | বেশি জটিল এবং ডেটার সাথে কাজ করতে উপযোগী। | সহজ, ছোট কাজগুলোর জন্য উপযোগী। |
সারাংশ
Spring Batch এ Chunk-based Step এবং Tasklet-based Step দুটি আলাদা ধরনের প্রসেসিং মডেল। Chunk-based Step বৃহত্তর ডেটাসেট নিয়ে কাজ করতে উপযোগী, যেখানে ডেটা ছোট ছোট অংশে ভাগ করে প্রসেস করা হয় এবং প্রতিটি chunk প্রসেস করার পর ডেটা কমিট করা হয়। অন্যদিকে, Tasklet-based Step একক কাজের জন্য ব্যবহৃত হয়, যেখানে একটি নির্দিষ্ট কাজ একবারে সম্পন্ন হয়। উভয় মডেলই Spring Batch এ ব্যাচ প্রসেসিংয়ের জন্য গুরুত্বপূর্ণ ভূমিকা পালন করে, এবং উপযুক্ত পরিস্থিতিতে প্রতিটি মডেল ব্যবহার করা যেতে পারে।
Spring Batch এর একটি গুরুত্বপূর্ণ অংশ হল Step Configuration, যেখানে একটি Step এর মাধ্যমে একটি ব্যাচ প্রোগ্রামে একাধিক কাজ সম্পন্ন করা হয়। Step একটি নির্দিষ্ট কাজের সেটকে নির্দেশ করে, যেমন ডেটা রিড করা, প্রোসেস করা এবং রাইট করা। প্রতিটি Step সাধারণত একটি ItemReader, ItemProcessor, এবং ItemWriter ব্যবহার করে কাজ সম্পন্ন করে।
এখানে একটি Step Configuration এর উদাহরণ দেওয়া হবে, যেখানে Spring Batch এর বিভিন্ন কনফিগারেশন ব্যবহার করে একটি Step তৈরি করা হবে।
1. প্রয়োজনীয় ডিপেনডেন্সি ইনস্টল করা
Spring Batch অ্যাপ্লিকেশন তৈরি করতে হলে প্রথমে spring-boot-starter-batch ডিপেনডেন্সি pom.xml ফাইলে যোগ করতে হবে।
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Batch -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
</dependency>
<!-- H2 Database for in-memory DB (optional) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
এখানে, spring-batch-core ডিপেনডেন্সি Spring Batch এর প্রধান কার্যকারিতা প্রদান করে এবং H2 ডাটাবেস (যদি আপনি ডেটাবেস ব্যবহার করতে চান) একটি ইন-মেমরি ডেটাবেস হিসেবে ব্যবহার করা হচ্ছে।
2. Step Configuration তৈরি করা
Spring Batch এ Step তৈরি করতে হলে ItemReader, ItemProcessor, এবং ItemWriter এর কম্পোনেন্টগুলো কনফিগার করা হয়।
2.1 Step কনফিগারেশন ক্লাস
package com.example.batch.config;
import com.example.batch.model.User;
import com.example.batch.processor.UserItemProcessor;
import com.example.batch.reader.UserItemReader;
import com.example.batch.writer.UserItemWriter;
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.Job;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class BatchConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
public BatchConfig(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
@Bean
public Job userJob() {
return jobBuilderFactory.get("userJob")
.incrementer(new RunIdIncrementer())
.start(userStep())
.build();
}
@Bean
public Step userStep() {
return stepBuilderFactory.get("userStep")
.<User, User>chunk(10) // Process 10 items at a time
.reader(userItemReader())
.processor(userItemProcessor())
.writer(userItemWriter())
.build();
}
@Bean
public UserItemReader userItemReader() {
return new UserItemReader();
}
@Bean
public UserItemProcessor userItemProcessor() {
return new UserItemProcessor();
}
@Bean
public UserItemWriter userItemWriter() {
return new UserItemWriter();
}
}
এখানে:
- Job কনফিগারেশন করা হয়েছে, যেখানে
userStep()নামক Step কে অন্তর্ভুক্ত করা হয়েছে। - Step কনফিগারেশনে
chunk(10)পদ্ধতি ব্যবহার করা হয়েছে, যা প্রতি 10টি আইটেম একসাথে প্রসেস করবে। - ItemReader, ItemProcessor, এবং ItemWriter গুলি Bean হিসেবে কনফিগার করা হয়েছে।
3. Reader, Processor এবং Writer তৈরি করা
এখন, ItemReader, ItemProcessor, এবং ItemWriter ক্লাসগুলো তৈরি করা হবে, যেগুলি Step এর মধ্যে কাজ করবে।
3.1 ItemReader তৈরি করা
ItemReader ক্লাসটি ডেটা পড়ার জন্য ব্যবহৃত হয়। এখানে, UserItemReader ক্লাস একটি সিম্পল ইউজার ডেটা রিডার হিসেবে কাজ করবে।
package com.example.batch.reader;
import com.example.batch.model.User;
import org.springframework.batch.item.ItemReader;
import java.util.Arrays;
import java.util.List;
public class UserItemReader implements ItemReader<User> {
private final List<User> users = Arrays.asList(
new User("John", "john@example.com"),
new User("Jane", "jane@example.com"),
new User("Bob", "bob@example.com")
);
private int index = 0;
@Override
public User read() throws Exception {
if (index < users.size()) {
return users.get(index++);
}
return null; // Return null when all items are read
}
}
এখানে, UserItemReader একটি স্ট্যাটিক লিস্ট থেকে ইউজার ডেটা রিড করে। প্রতিবার কল করার সময় এটি পরবর্তী ইউজার অবজেক্ট রিটার্ন করবে।
3.2 ItemProcessor তৈরি করা
ItemProcessor ডেটা প্রসেস করার জন্য ব্যবহৃত হয়। এখানে, UserItemProcessor ক্লাসের মধ্যে ডেটা প্রসেস করা হবে।
package com.example.batch.processor;
import com.example.batch.model.User;
import org.springframework.batch.item.ItemProcessor;
public class UserItemProcessor implements ItemProcessor<User, User> {
@Override
public User process(User item) throws Exception {
item.setName(item.getName().toUpperCase()); // Convert name to uppercase
return item;
}
}
এখানে, UserItemProcessor প্রতিটি User অবজেক্টের নামকে uppercase তে রূপান্তর করবে।
3.3 ItemWriter তৈরি করা
ItemWriter ডেটা লেখার জন্য ব্যবহৃত হয়। এখানে, UserItemWriter ক্লাস কনসোলে প্রোসেস করা ডেটা লেখবে।
package com.example.batch.writer;
import com.example.batch.model.User;
import org.springframework.batch.item.ItemWriter;
import java.util.List;
public class UserItemWriter implements ItemWriter<User> {
@Override
public void write(List<? extends User> items) throws Exception {
for (User user : items) {
System.out.println("Writing user: " + user);
}
}
}
এখানে, UserItemWriter প্রোসেস করা User অবজেক্টগুলি কনসোলে প্রিন্ট করে।
4. User Model ক্লাস
এখন, আমাদের একটি User মডেল ক্লাস তৈরি করতে হবে, যেটি ডেটা রিড, প্রোসেস এবং রাইট করার জন্য ব্যবহৃত হবে।
package com.example.batch.model;
public class User {
private String name;
private String email;
// Constructor
public User(String name, String email) {
this.name = name;
this.email = email;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{name='" + name + "', email='" + email + "'}";
}
}
এখানে, User ক্লাসের মধ্যে নাম এবং ইমেইল ফিল্ড রয়েছে এবং সেগুলির জন্য গেটার এবং সেটার মেথড রয়েছে।
5. Batch Job চালানো
Spring Batch অ্যাপ্লিকেশন চালানোর জন্য, আপনি BatchConfig কনফিগারেশন ক্লাসে JobLauncher ব্যবহার করে জব রান করতে পারেন।
5.1 Job Execution
package com.example.batch;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobExecution;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BatchApplication {
public static void main(String[] args) throws JobExecutionException {
ApplicationContext context = new AnnotationConfigApplicationContext(BatchConfig.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean("userJob", Job.class);
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Job Status : " + execution.getStatus());
}
}
এখানে, JobLauncher ব্যবহার করে userJob রান করা হয়েছে। এক্সিকিউশনের স্ট্যাটাস কনসোলে প্রদর্শিত হবে।
সারাংশ
Spring Batch এর মাধ্যমে আপনি Step Configuration ব্যবহার করে ব্যাচ প্রসেস তৈরি করতে পারেন। ItemReader, ItemProcessor, এবং ItemWriter এর মাধ্যমে ডেটা রিড, প্রোসেস এবং রাইট করার কাজ করা হয়। এই উদাহরণে, আমরা দেখেছি কিভাবে একটি User ব্যাচ প্রসেস তৈরি করতে হয় এবং প্রতিটি Step এ ডেটা প্রোসেস করা হয়। Spring Batch বড় আকারের ডেটা প্রসেসিংয়ে সহায়ক এবং স্কেলেবল একটি ফ্রেমওয়ার্ক।
Read more