ここでは、Spring Boot + SLF4J(Logback) を前提にした、
「for-each+例外処理+ロギング」を安全かつ拡張性高く実装する 実務テンプレート を紹介します。
これは実際の業務システム(バッチ処理・ETL・データ連携など)で
“安全に全件処理を継続する”ためのベース設計としてそのまま使える構成です。
Spring Boot+SLF4J対応 for-each 安全処理テンプレート
package com.example.processor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 拡張for文を安全に処理する共通テンプレート
*/
@Slf4j
@Service
public class SafeForEachProcessor<T> {
/**
* for-each処理を安全に実行(例外とログを統一管理)
*/
public void process(List<T> items, SafeHandler<T> handler) {
if (items == null || items.isEmpty()) {
log.warn("処理対象リストが空またはnullです。スキップします。");
return;
}
int successCount = 0;
int failureCount = 0;
for (T item : items) {
try {
handler.handle(item);
successCount++;
} catch (BusinessException e) {
failureCount++;
log.warn("業務エラー(スキップ): {} -> {}", item, e.getMessage());
} catch (Exception e) {
failureCount++;
log.error("予期せぬ例外発生: {}", item, e);
}
}
log.info("処理完了: 成功={}件 / 失敗={}件 / 合計={}件",
successCount, failureCount, items.size());
}
}
Java関連クラス構成(業務利用例)
SafeHandler.java(ラムダで処理定義)
package com.example.processor;
@FunctionalInterface
public interface SafeHandler<T> {
void handle(T item) throws Exception;
}
JavaBusinessException.java(想定内エラー)
package com.example.processor;
public class BusinessException extends Exception {
public BusinessException(String message) {
super(message);
}
}
JavaCustomer.java(ドメインモデル例)
package com.example.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Customer {
private String name;
private int age;
}
JavaCustomerService.java(業務ロジック例)
package com.example.service;
import com.example.model.Customer;
import com.example.processor.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class CustomerService {
public void processCustomer(Customer customer) throws BusinessException {
if (customer.getAge() < 0) {
throw new BusinessException("年齢が不正: " + customer);
}
// 実際の処理(DB更新・外部API呼び出しなど)
log.info("顧客処理中: {}", customer.getName());
}
}
JavaBatchJob.java(バッチ的な呼び出し例)
package com.example.job;
import com.example.model.Customer;
import com.example.processor.SafeForEachProcessor;
import com.example.service.CustomerService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
@RequiredArgsConstructor
public class BatchJob {
private final SafeForEachProcessor<Customer> processor;
private final CustomerService customerService;
public void run() {
List<Customer> customers = Arrays.asList(
new Customer("Alice", 25),
new Customer("Bob", -1),
new Customer("Charlie", 30)
);
processor.process(customers, customerService::processCustomer);
}
}
JavaDemoApplication.java(起動クラス)
package com.example;
import com.example.job.BatchJob;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
private final BatchJob batchJob;
public DemoApplication(BatchJob batchJob) {
this.batchJob = batchJob;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) {
batchJob.run();
}
}
Java実行結果ログ(例)
INFO com.example.processor.SafeForEachProcessor - 処理対象リスト: 3件
INFO com.example.service.CustomerService - 顧客処理中: Alice
WARN com.example.processor.SafeForEachProcessor - 業務エラー(スキップ): Customer(name=Bob, age=-1) -> 年齢が不正: Customer(name=Bob, age=-1)
INFO com.example.service.CustomerService - 顧客処理中: Charlie
INFO com.example.processor.SafeForEachProcessor - 処理完了: 成功=2件 / 失敗=1件 / 合計=3件
実務ベストプラクティスまとめ
| 項目 | ベストプラクティス | 理由 |
|---|---|---|
| ログ出力にSLF4J+Logback | System.out禁止。統一されたフォーマット+レベル管理可能。 | |
| for-each内で個別try-catch | 1件失敗しても全体継続できる。バッチ処理の基本。 | |
| 共通テンプレート化 | 全サービスで同じ安全基盤を使い回せる。例外処理重複を削減。 | |
| ビジネス例外クラスを分離 | 想定内エラーと致命的障害を区別可能。監視・通知設定がしやすい。 | |
| DI構成(Spring管理) | テスト容易性・拡張性が高い(Mock化・単体テスト可能)。 | |
| 結果サマリー出力 | 運用監視で「件数把握」が非常に重要。 |
発展案(次ステップ)
| 機能 | 説明 |
|---|---|
| 🔁 リトライ付き処理(一定回数まで再実行) | API連携や一時障害に強い |
| 🧮 処理結果オブジェクト(成功件数・失敗リスト)返却 | 集計レポート生成に利用 |
| 🪶 非同期処理(@Async)対応版 | 並列実行でバッチ性能向上 |
| 🧱 テストテンプレート(JUnit+MockBean) | 安全動作を検証しやすくする |

