概要

バッチ処理で入力ファイルのパスや DB 接続先をソースコードに直書きしていると、環境が変わるたびにビルドし直す必要が出てきます。java.util.Properties は古い API ですが、キーと値のペアを外部ファイルに持たせる用途では今でも十分に実用的です。この記事では、Properties ファイルの読み込みを BatchConfig クラスとしてラップし、デフォルト値の設定、必須パラメータの存在チェック、環境ごとの設定ファイル切替(開発/ステージング/本番)を整理します。前回の CsvImportJob に BatchConfig を組み込み、入力ファイルパスやエンコーディングを設定ファイルから注入する実装例も示します。

使いどころ

バッチの入力ファイルパス・出力先を環境ごとに切り替え、デプロイ時のミスを減らす

DB 接続情報を設定ファイルに外出しし、ソースコードから機密情報を除去する

リトライ回数やタイムアウト秒数を再ビルドなしで変更可能にする

コード例

BatchConfig クラス
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.logging.Logger;

public class BatchConfig {
    private static final Logger LOGGER = Logger.getLogger(BatchConfig.class.getName());
    private final Properties properties;

    private BatchConfig(Properties properties) { this.properties = properties; }

    public static BatchConfig load(String filePath) throws IOException {
        Properties props = new Properties();
        FileInputStream fis = new FileInputStream(filePath);
        InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
        try { props.load(reader); } finally { reader.close(); fis.close(); }
        LOGGER.info("設定ファイル読込: " + filePath + " (" + props.size() + "件)");
        return new BatchConfig(props);
    }

    public static BatchConfig loadForEnv(String baseDir, String env) throws IOException {
        String envFile = baseDir + File.separator + "batch-" + env + ".properties";
        String defaultFile = baseDir + File.separator + "batch.properties";
        return new File(envFile).exists() ? load(envFile) : load(defaultFile);
    }

    public String get(String key, String defaultValue) {
        return Optional.ofNullable(properties.getProperty(key)).orElse(defaultValue);
    }

    public String getRequired(String key) {
        String value = properties.getProperty(key);
        if (value == null || value.trim().isEmpty()) {
            throw new IllegalStateException("必須パラメータ未設定: " + key);
        }
        return value.trim();
    }

    public int getInt(String key, int defaultValue) {
        String value = properties.getProperty(key);
        if (value == null || value.trim().isEmpty()) return defaultValue;
        try { return Integer.parseInt(value.trim()); } catch (NumberFormatException e) {
            LOGGER.warning("int変換失敗: " + key + "=" + value); return defaultValue;
        }
    }

    public boolean getBoolean(String key, boolean defaultValue) {
        String value = properties.getProperty(key);
        return value != null ? Boolean.parseBoolean(value.trim()) : defaultValue;
    }

    public List<String> validateRequired(String... keys) {
        List<String> missing = new ArrayList<String>();
        for (String key : keys) {
            String v = properties.getProperty(key);
            if (v == null || v.trim().isEmpty()) missing.add(key);
        }
        return missing;
    }

    public static void main(String[] args) throws IOException {
        BatchConfig config = BatchConfig.load("config/batch.properties");
        System.out.println("input.file = " + config.get("input.file", "(未設定)"));
        System.out.println("input.charset = " + config.get("input.charset", "UTF-8"));
        System.out.println("batch.maxErrors = " + config.getInt("batch.maxErrors", 100));
    }
}

Java 8 / 17 / 21 の完全なサンプルコードは GitHub リポジトリ で確認できます。

Version Coverage

NIO の Files.newBufferedReader で Charset を明示的に渡せるため文字コードの扱いが簡潔になる。

Java 17
// Java 17: Files.newBufferedReader で簡潔に
var props = new Properties();
try (var reader = Files.newBufferedReader(
        Path.of("batch.properties"), StandardCharsets.UTF_8)) {
    props.load(reader);
}

Library Comparison

Pure Java(java.util.Properties)フラットな key=value で十分な場合。依存ゼロでバッチの設定を外部化したいとき。ネスト構造やリスト、型安全な読み込みには対応していない。
Apache Commons Configuration複数形式(properties、XML、YAML)を統一的に扱いたい場合。Commons 系の依存が増える。単純な key=value には過剰。
typesafe config (HOCON)ネスト構造、型安全な取得、include が必要な場合。HOCON 独自記法の学習コスト。Properties で済むなら不要。

注意点

Properties ファイルはデフォルトで ISO 8859-1。日本語を含む場合は Reader で UTF-8 を指定する

パスワードを平文で置く場合、ファイルのパーミッション管理が必須。.gitignore に追加すること

getProperty() は存在しないキーに null を返す。必須パラメータは起動時にまとめて検証する

System.getProperty() と Properties ファイルの優先順位を明確に決めておくこと

int や boolean への変換時の NumberFormatException に防御を忘れないこと

FAQ

properties ファイルに日本語を書くには。

Properties.load(Reader) で UTF-8 の InputStreamReader を渡せばそのまま書けます。load(InputStream) は ISO 8859-1 前提です。

環境ごとの設定ファイル切替はどう実現しますか。

起動引数で環境名を渡し、batch-{env}.properties を読み込む方式が一般的です。

設定値のバリデーションはいつ行うべきですか。

バッチ起動直後の initialize() 先頭で全必須パラメータを一括検証し、不足があれば早期に異常終了させます。

関連書籍

この記事のテーマをさらに深く学びたい方へ。

※ Amazon アソシエイトリンクを含みます