| この記事の要点 |
|
原因:jar の中のファイルはパスでは読めない
開発環境では普通にパス指定すれば jasper ファイルなどのリソースファイルは読み込めますが、本番環境にデプロイする際に jar にするとファイルが読み込めなくなります。
IDE から実行しているときは、src/main/resources の中身がビルド先のディレクトリ(target/classes など)に普通のファイルとして存在するため、"src/main/resources/jasper/sub_report.jasper" のようなパスでも動いてしまいます。ところが jar にすると、これらは jar(zip 形式)の中のエントリになり、OS のファイルパスでは開けません。
従って、リソースファイルを指定する際は通常のパスではなくURL などクラスパス経由で読める形で指定する必要があります。メインレポートだろうがサブレポートだろうが同じです。メインレポート側の読み込み方は別記事「jar内のjrxml/jasperファイルを読み込む方法」を参照してください。
方法 1:jasper ディレクトリの URL をパラメータで渡す
jasper 内で URL を取得するより、Java 側で取得してパラメータとして渡してやるのがおすすめです。下記の例では「src/main/resources/jasper」配下に jasper ファイルが格納されている前提で、jasper ディレクトリまでの URL を取得しています。
// 末尾のスラッシュまで含めた URL 文字列にしておく
String jasperResourceUrl = this.getClass().getResource("/jasper/").toString();
// 例: jar:file:/opt/app/app.jar!/jasper/ (通常の jar)
// file:/home/dev/project/target/classes/jasper/ (IDE 実行時)
Map<String, Object> params = new HashMap<>();
params.put("jasperResourceUrl", jasperResourceUrl);
getResource("/jasper") のように末尾のスラッシュを付けないと、URL がスラッシュで終わらず、後でファイル名と結合したときに .../jaspersub_report.jasper という誤ったパスになるので注意してください。
jrxml 側では、パラメータ(jasperResourceUrl)として受け取った jasper ディレクトリまでの URL とファイル名を結合して、サブレポートとして読み込みます。
<parameter name="jasperResourceUrl" class="java.lang.String"/>
<!-- サブレポート要素の中 -->
<subreportExpression><![CDATA[$P{jasperResourceUrl} + "sub_report.jasper"]]></subreportExpression>
Jaspersoft Studio でサブレポートを配置すると、$P{SUBREPORT_DIR} + "sub_report.jasper" のような式とパラメータ SUBREPORT_DIR が自動で作られることがあります。その場合は Java 側で params.put("SUBREPORT_DIR", jasperResourceUrl) として値を差し替えれば、jrxml を書き換えずに済みます。
方法 2:JasperReport オブジェクトを渡す(おすすめ)
サブレポートの式には、文字列(パスや URL)だけでなく、読み込み済みの JasperReport オブジェクトも渡せます。Java 側でクラスパスから読み込んでおけば、jar かどうか・URL の形式がどうなるかを気にする必要がありません。
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.util.JRLoader;
JasperReport mainReport;
JasperReport subReport;
try (InputStream main = getClass().getResourceAsStream("/jasper/main_report.jasper");
InputStream sub = getClass().getResourceAsStream("/jasper/sub_report.jasper")) {
mainReport = (JasperReport) JRLoader.loadObject(main);
subReport = (JasperReport) JRLoader.loadObject(sub);
}
Map<String, Object> params = new HashMap<>();
params.put("SUB_REPORT", subReport);
JasperPrint print = JasperFillManager.fillReport(mainReport, params, connection);
<parameter name="SUB_REPORT" class="net.sf.jasperreports.engine.JasperReport"/>
<subreportExpression><![CDATA[$P{SUB_REPORT}]]></subreportExpression>
同じサブレポートを何度も使う場合でも、読み込みは 1 回で済むため効率的です。コンパイル済みの JasperReport はアプリ内でキャッシュしておくこともできます。
サブレポートにデータを渡すのも忘れずに
サブレポートが自分で SQL を実行する場合は、メインレポートの DB 接続を引き継ぐ設定が必要です。これがないと、サブレポートの読み込み自体は成功しても何も表示されません。
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
Java Bean のリストなどをデータソースにする場合は dataSourceExpression で JRBeanCollectionDataSource などを渡します。
よくある落とし穴
- getResource が null を返す: パスの指定ミス。先頭の
/はクラスパスのルートを意味する。src/main/resources/jasper/x.jasperなら/jasper/x.jasperと書く - jrxml だけを同梱している: サブレポートに
.jasperを指定しているのに、jar にはコンパイル前の.jrxmlしか入っていないケース。ビルド時にコンパイルして同梱するか、実行時にJasperCompileManager.compileReport()でコンパイルする - コンパイルしたバージョンの違い: Jaspersoft Studio でコンパイルした .jasper と、アプリが使う JasperReports ライブラリのバージョンが大きく違うと、読み込み時に例外が出ることがある。ライブラリと同じバージョンでコンパイルするのが安全
- Spring Boot の実行可能 jar: クラスは
BOOT-INF/classes配下に入るため URL の形が通常の jar と異なる。方法 2 なら URL の形に依存しない - File クラスで扱おうとする:
new File(url.toURI())のように URL を File に変換するコードは jar 内では失敗する(URI is not hierarchical など)
確認方法
- jar に jasper ファイルが含まれているかを確認する
jar tf app.jar | grep jasper - 取得した URL をログに出し、末尾のスラッシュや
!/以降のパスが正しいか確認する - IDE 実行ではなく、
java -jar app.jarで起動して帳票を出力し、サブレポート部分が表示されるか確認する
関連
- Spring classpath: プレフィックス|src/main/resources のリソース読み込み
- Spring Bootプロジェクトのビルドと本番環境へのデプロイ方法(内部tomcat使用)
- Java Web アプリのデプロイ方法まとめ(WAR / Spring Boot jar / Docker / CI/CD)
- Maven 完全ガイド (pom.xml / ライフサイクル / プラグイン / リポジトリ)
子ページはありません
- 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