概要
バッチ処理で入力ファイルのパスや DB 接続先をソースコードに直書きしていると、環境が変わるたびにビルドし直す必要が出てきます。java.util.Properties は古い API ですが、キーと値のペアを外部ファイルに持たせる用途では今でも十分に実用的です。この記事では、Properties ファイルの読み込みを BatchConfig クラスとしてラップし、デフォルト値の設定、必須パラメータの存在チェック、環境ごとの設定ファイル切替(開発/ステージング/本番)を整理します。前回の CsvImportJob に BatchConfig を組み込み、入力ファイルパスやエンコーディングを設定ファイルから注入する実装例も示します。
使いどころ
バッチの入力ファイルパス・出力先を環境ごとに切り替え、デプロイ時のミスを減らす
DB 接続情報を設定ファイルに外出しし、ソースコードから機密情報を除去する
リトライ回数やタイムアウト秒数を再ビルドなしで変更可能にする
コード例
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));
}
}Version Coverage
NIO の Files.newBufferedReader で Charset を明示的に渡せるため文字コードの扱いが簡潔になる。
// 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
注意点
Properties ファイルはデフォルトで ISO 8859-1。日本語を含む場合は Reader で UTF-8 を指定する
パスワードを平文で置く場合、ファイルのパーミッション管理が必須。.gitignore に追加すること
getProperty() は存在しないキーに null を返す。必須パラメータは起動時にまとめて検証する
System.getProperty() と Properties ファイルの優先順位を明確に決めておくこと
int や boolean への変換時の NumberFormatException に防御を忘れないこと
FAQ
Properties.load(Reader) で UTF-8 の InputStreamReader を渡せばそのまま書けます。load(InputStream) は ISO 8859-1 前提です。
起動引数で環境名を渡し、batch-{env}.properties を読み込む方式が一般的です。
バッチ起動直後の initialize() 先頭で全必須パラメータを一括検証し、不足があれば早期に異常終了させます。