| この記事の要点 |
|
症状
開発環境(Eclipse や IntelliJ IDEA から実行)では普通にパス指定すれば jrxml ファイルなどのリソースファイルを読み込めるのに、本番環境にデプロイするために jar(Spring Boot の実行可能 jar を含む)にすると、ファイルが読み込めなくなることがあります。典型的には次のような例外になります。
java.io.FileNotFoundException: src/main/resources/jrxml/test.jrxml (No such file or directory)
java.nio.file.FileSystemNotFoundException
net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: ...
原因: jar の中のリソースはファイルシステム上に存在しない
IDE から実行しているときは、src/main/resources や target/classes が実際のフォルダとしてディスク上に存在するため、相対パスや File で読めてしまいます。
ところが jar にすると、リソースは zip 形式の jar ファイルの中に格納されます。jar の中身には OS のファイルパスが存在しないため、new File(...) や FileInputStream では開けません。また、getResource() で取った URL を Paths.get(url.toURI()) でファイルパスに変換しようとすると、jar:file:...!/jrxml/test.jrxml という形式の URL になるため FileSystemNotFoundException になります。
したがって、リソースファイルを指定する際は通常のファイルパスではなく、クラスパス上のリソースとして URL か InputStream で読む必要があります。
対処法: クラスパスから読み込む
以下は URL を取得して jrxml を読み込む例です。jrxml は src/main/resources/jrxml ディレクトリ内にあるものとします。
String path = "/jrxml/test.jrxml";
URL url = this.getClass().getResource(path);
JasperReport jr = JasperCompileManager.compileReport(url.openStream());
実務では、InputStream を直接取得して try-with-resources で確実に閉じる書き方がおすすめです。
import java.io.InputStream;
import net.sf.jasperreports.engine.*;
try (InputStream in = getClass().getResourceAsStream("/jrxml/test.jrxml")) {
if (in == null) {
throw new IllegalStateException("jrxml が見つかりません: /jrxml/test.jrxml");
}
JasperReport report = JasperCompileManager.compileReport(in);
JasperPrint print = JasperFillManager.fillReport(report, params, dataSource);
JasperExportManager.exportReportToPdfFile(print, "/tmp/out.pdf");
}
コンパイル済みの .jasper を読む場合
帳票を出すたびに jrxml をコンパイルすると時間がかかるため、事前にコンパイルした .jasper を jar に含めておく方法もよく使われます。この場合はコンパイル不要で、次のように読み込みます。
try (InputStream in = getClass().getResourceAsStream("/jasper/test.jasper")) {
JasperReport report = (JasperReport) JRLoader.loadObject(in);
JasperPrint print = JasperFillManager.fillReport(report, params, dataSource);
}
JasperFillManager.fillReport(InputStream, Map, ...) のように、.jasper の InputStream を直接受け取るオーバーロードもあります。JRLoader は net.sf.jasperreports.engine.util パッケージのクラスです。
パスの書き方: 先頭スラッシュの有無
| 書き方 | 基準 | 例 |
|---|---|---|
| Class#getResource("/jrxml/a.jrxml") | クラスパスのルート | resources/jrxml/a.jrxml を読む |
| Class#getResource("jrxml/a.jrxml") | そのクラスのパッケージ | com/example/jrxml/a.jrxml を探してしまう |
| ClassLoader#getResource("jrxml/a.jrxml") | クラスパスのルート(先頭スラッシュは付けない) | resources/jrxml/a.jrxml を読む |
先頭スラッシュを付け忘れて null が返り、NullPointerException になるのはよくあるミスです。上の例のように null チェックを入れておくと、原因がすぐに分かります。
Spring Boot での書き方
Spring を使っている場合は、ClassPathResource や ResourceLoader を使うと読みやすくなります。
import org.springframework.core.io.ClassPathResource;
ClassPathResource res = new ClassPathResource("jrxml/test.jrxml");
try (InputStream in = res.getInputStream()) {
JasperReport report = JasperCompileManager.compileReport(in);
}
res.getFile() は jar の中では使えない(例外になる)ので、必ず getInputStream() を使ってください。
よくある落とし穴
- リソースが jar に含まれていない:
src/main/java側に jrxml を置くと、Maven の既定設定ではビルド時にコピーされない。src/main/resourcesに置く - 大文字小文字の違い: Windows の開発環境では Test.jrxml と test.jrxml が同じ扱いになるが、jar 内や Linux では区別される
- サブレポートや画像のパス: jrxml 内で指定するサブレポート・画像のパスも、ファイルパスのままだと同じ問題が起きる。パラメータで InputStream や JasperReport オブジェクトを渡す方法に変える
- フォントの扱い: PDF 出力で日本語フォントを使う場合、フォント拡張の jar がクラスパスに含まれているかも確認する
確認方法
jar tf app.jar | grep jrxmlで、リソースが jar 内のどのパスに入っているか確認する(Spring Boot の jar ではBOOT-INF/classes/以下がクラスパスのルート)java -jar app.jarで起動し、IDE ではなく jar の状態で帳票が出力できるか確かめるgetResourceAsStreamの戻り値が null でないことをログで確認する
関連
- Java Web アプリのデプロイ方法まとめ(WAR / Spring Boot jar / Docker / CI/CD)
- Maven 完全ガイド (pom.xml / ライフサイクル / プラグイン / リポジトリ)
- Spring Boot プロジェクトの実行方法(mvn / gradle / jar / IDE / プロファイル)
- Hibernate MappingException Error reading resource の原因と対処
子ページはありません
- jar内のjrxml/jasperファイルを読み込む方法
- jar内のサブレポートを読み込む方法
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Visual Studio「デザイナーを表示できません」エラーの原因と対処 2026-10-28 12:06:00
- SSH 認証に失敗しました。再試行してください の対処 2026-10-28 12:06:00
- SSH2 秘密鍵の読み込みに失敗しました の原因と対処 2026-10-28 12:06:00
- TeraTerm のよくあるエラーと対処法完全ガイド — Connection refused / 2026-10-28 12:06:00
- Visual Studio エラー一覧|コンパイルエラー・警告の確認方法と対処 2026-10-28 11:39:57
- Whitelabel Error Page の原因と消し方|Spring Boot のエラーページ 2026-10-28 11:39:57
- Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法 2026-10-28 11:39:57
- SQL WHERE 句完全ガイド 2026-10-28 11:39:57
- SQL JOIN 完全ガイド (INNER/LEFT/RIGHT/FULL OUTER) 2026-10-28 11:39:57
- tomcat の起動 / 停止ログと catalina.log・catalina.out の違い 2026-10-28 10:24:23
- Tomcat の起動確認方法 5 つ|localhost:8080・ポート・プロセス・ログ 2026-10-28 10:24:23
- Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認 2026-10-28 09:59:09
- Oracle 19c DELETE文|削除対象の確認・COMMIT前の判断・ROLLBACKの条件 2026-10-28 09:59:09
- Oracle 19c INSERT文|INSERT ALL・SELECT・RETURNINGとMERGEの使い分け 2026-10-28 09:59:09
- Oracle 19cのトランザクション制御|COMMIT・ROLLBACK・分離レベルと接続設定 2026-10-28 09:59:09