1. 序章

このチュートリアルでは、BIRT(ビジネスインテリジェンスおよびレポートツール)をSpring Boot MVCと統合して、静的および動的なレポートをHTMLおよびPDF形式で提供します。

2. BIRT とは何ですか?

BIRTは、JavaWebアプリケーションに統合できるデータ視覚化を作成するためのオープンソースエンジンです。

これはEclipseFoundation内のトップレベルのソフトウェアプロジェクトであり、IBMとInnoventSolutionsによる貢献を活用しています。 これは、2004年の終わりにActuateによって開始され、後援されました。

このフレームワークにより、さまざまなデータソースと統合されたレポートを作成できます。

3. Mavenの依存関係

BIRTには、レポートデザインファイルを作成するためのビジュアルレポートデザイナーと、それらのデザインを解釈およびレンダリングするためのランタイムコンポーネントの2つの主要コンポーネントがあります。

この例のWebアプリケーションでは、Spring Bootの上に両方を使用します。

3.1. BIRTフレームワークの依存関係

依存関係の管理という観点から考えることに慣れているため、最初の選択肢はMavenCentralでBIRTを探すことです。

ただし、利用可能なコアライブラリの最新の公式バージョンは2016 から4.6ですが、 Eclipseダウンロードページには、少なくとも2つの新しいバージョン(現在は4.8)です。

公式ビルドを選択した場合、コードを起動して実行する最も簡単な方法は、 BIRT Report Engine パッケージをダウンロードすることです。これは、学習にも役立つ完全なWebアプリケーションです。 次に、その lib フォルダーをプロジェクト(サイズは約68MB)にコピーし、IDEにすべてのjarファイルを含めるように指示する必要があります。

言うまでもなく、このアプローチを使用すると、 IDE を介してのみコンパイルできます。これは、手動で構成してインストールしない限り、Mavenがこれらのjarを検出しないためです(100ファイル以上!)私たちのローカルリポジトリで。

幸い、 Innovent Solutionsは問題を処理することを決定し、Maven Centralで最新のBIRT依存関係の独自のビルドを公開しました。これは、必要なすべての依存関係を管理するので素晴らしいことです。

オンラインフォーラムのコメントを読むと、これらのアーティファクトが本番環境に対応しているかどうかは不明ですが、Innovent Solutionsは開始以来Eclipseチームの隣のプロジェクトに取り組んでいたため、プロジェクトはそれらに依存しています。

BIRTを含めるのは非常に簡単です。

<dependency>
    <groupId>com.innoventsolutions.birt.runtime</groupId>
    <artifactId>org.eclipse.birt.runtime_4.8.0-20180626</artifactId>
    <version>4.8.0</version>
</dependency>

3.2. SpringBootの依存関係

BIRTがプロジェクトにインポートされたので、pomファイルに標準のSpringBoot依存関係を追加する必要があります。

ただし、1つの落とし穴があります。これは、BIRTjarにSlf4J の独自の実装が含まれているため、 Logback とうまく連携せず、起動時に競合例外がスローされるためです。

jarから削除できないため、この問題を修正するには、Logbackを除外する必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>

これで、ようやく開始する準備が整いました。

4. BIRTレポート

BIRTフレームワークでは、レポートは長いXML構成ファイルであり、拡張子rptdesignで識別されます。

タイトルのスタイルからデータソースに接続するために必要なプロパティまで、何をどこに描画するかをエンジンに指示します。

基本的な動的レポートの場合、次の3つを構成する必要があります。

  1. データソース(この例ではローカルCSVファイルを使用していますが、データベーステーブルである可能性があります)
  2. 表示したい要素(グラフ、表など)
  3. ページデザイン

レポートは、ヘッダー、本文、フッター、スクリプト、およびスタイルを備えたHTMLページのように構成されています。

フレームワークは、主流のデータソース、レイアウト、チャート、およびテーブルへの統合を含む、すぐに使用できるから選択できる広範なコンポーネントのセットを提供します。 そして、それを拡張して独自のものを追加することができます!

レポートファイルを生成するには、ビジュアルまたはプログラムの2つの方法があります。

5. Eclipseレポートデザイナ

レポートの作成を容易にするために、 Eclipseチームは、人気のあるIDE用のレポートデザインツールプラグインを作成しました。

このツールは、簡単なドラッグアンドドロップインターフェイスを備えていますからパレット左側には、ページに追加する新しいコンポーネントのセットアップウィンドウが自動的に開きます。 また、ページをクリックしてからプロパティエディタボタン(下の画像で強調表示)をクリックすると、各コンポーネントで利用可能なすべてのカスタマイズを確認できます。

ページ構造全体をツリービューで視覚化するには、アウトラインボタンをクリックするだけです。

データエクスプローラータブには、レポート用に定義されたデータソースも含まれています。

画像に表示されているサンプルレポートは、パスにあります。 /reports/csv_data_report.rptdesign

ビジュアルデザイナーを選ぶもう1つの利点は、プログラムによるアプローチではなく、このツールに重点を置いたオンラインドキュメントです。

すでにEclipseを使用している場合は、事前定義されたパースペクティブとビジュアルエディターを含むBIRTレポートデザインプラグインをインストールする必要があります。

現在Eclipseを使用しておらず、切り替えたくない開発者向けに、 Eclipse Report Designerパッケージがあります。これは、BIRTプラグインがプリインストールされたポータブルEclipseインストールで構成されています。 。

レポートファイルが完成したら、それをプロジェクトに保存して、好みの環境でのコーディングに戻ることができます。

6. プログラマティックアプローチ

コードのみを使用してレポートを設計することもできますが、入手可能なドキュメントが不十分なため、このアプローチは非常に難しいため、ソースコードとオンラインフォーラムを掘り下げる準備をしてください。

また、サイズ、長さ、グリッド位置などの面倒なデザインの詳細はすべて、デザイナーを使用するとはるかに簡単に処理できることも考慮する価値があります。

この点を証明するために、画像とテキストを使用して単純な静的ページを定義する方法の例を次に示します。

DesignElementHandle element = factory.newSimpleMasterPage("Page Master");
design.getMasterPages().add(element);

GridHandle grid = factory.newGridItem(null, 2, 1);
design.getBody().add(grid);

grid.setWidth("100%"); 

RowHandle row0 = (RowHandle) grid.getRows().get(0);

ImageHandle image = factory.newImage(null);
CellHandle cell = (CellHandle) row0.getCells().get(0);
cell.getContent().add(image);
image.setURL("\"https://www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png\"");

LabelHandle label = factory.newLabel(null);
cell = (CellHandle) row0.getCells().get(1);
cell.getContent().add(label);
label.setText("Hello, Baeldung world!");

このコードは、単純な(そして醜い)レポートを生成します。

上の画像に表示されているサンプルレポートは、次のパスにあります。 /reports/static_report.rptdesign。

レポートの外観と表示するデータをコーディングしたら、ReportDesignApplicationクラスを実行してXMLファイルを生成できます。

7. データソースの添付

BIRTは多くの異なるデータソースをサポートしていることを前述しました。

この例のプロジェクトでは、3つのエントリを持つ単純なCSVファイルを使用しました。 reports フォルダーにあり、3つの単純なデータ行とヘッダーで構成されています。

Student, Math, Geography, History
Bill, 10,3,8
Tom, 5,6,5
Anne, 7, 4,9

7.1. データソースの構成

BIRTにファイル(または他のタイプのソース)を使用させるには、データソースを構成する必要があります。

このファイルでは、レポートデザイナーを使用してフラットファイルデータソースを作成しました。すべて、いくつかの手順で実行できます。

  1. デザイナーパースペクティブを開き、右側のアウトラインを見てください。
  2. データソースアイコンを右クリックします。
  3. 目的のソースタイプ(この場合はフラットファイルソース)を選択します。
  4. これで、フォルダ全体をロードするか、1つのファイルのみをロードするかを選択できます。 2番目のオプションを使用しました(データファイルがCSV形式の場合は、必ず最初の行を列名インジケーターとして使用します)。
  5. 接続をテストして、パスが正しいことを確認します。

各ステップを示すために、いくつかの写真を添付しました。

7.2. データセット

データソースの準備はできていますが、データセットを定義する必要があります。これは、レポートに表示される実際のデータです。

  1. デザイナーパースペクティブを開き、右側のアウトラインを見てください。
  2. データセットアイコンを右クリックします。
  3. 目的のデータソースとタイプを選択します(この場合、タイプは1つだけです)。
  4. 次の画面は、選択したデータソースとデータセットのタイプによって異なります。この場合、含める列を選択できるページが表示されます。
  5. セットアップが完了したら、データセットをダブルクリックしていつでも構成を開くことができます。
  6. 出力列では、表示されるデータの正しいタイプを設定できます。
  7. 次に、プレビュー結果をクリックしてプレビューを表示できます。

繰り返しますが、これらの手順を明確にするためのいくつかの写真:

7.3. その他のデータソースタイプ

データセット構成のステップ4で述べたように、使用可能なオプションは、参照されるデータソースに応じて変わる可能性があります。

CSVファイルの場合、BIRTには、表示する列、データ型、およびファイル全体を読み込むかどうかに関連するオプションがあります。 一方、JDBCデータソースがある場合は、SQLクエリまたはストアドプロシージャを作成する必要があります。

データセットメニューから、2つ以上のデータセットを新しいデータセットに結合することもできます。

8. レポートのレンダリング

レポートファイルの準備ができたら、レンダリングのためにエンジンに渡す必要があります。 これを行うには、実装することがいくつかあります。

8.1. エンジンの初期化

ReportEngine クラスは、設計ファイルを解釈して最終結果を生成し、BIRTランタイムライブラリの一部です。

たくさんのヘルパーとタスクを使用して仕事をし、非常に多くのリソースを消費します。

画像ソース:EclipseBIRTドキュメント

エンジンインスタンスの作成にはかなりのコストがかかります。これは主に拡張機能の読み込みコストが原因です。 したがって、 1つのReportEngineインスタンスのみを作成し、それを使用して複数のレポートを実行する必要があります

レポートエンジンは、プラットフォームが提供するファクトリを通じて作成されます。 エンジンを作成する前に、 Platform を起動する必要があります。これにより、適切なプラグインがロードされます。

@PostConstruct
protected void initialize() throws BirtException {
    EngineConfig config = new EngineConfig();
    config.getAppContext().put("spring", this.context);
    Platform.startup(config);
    IReportEngineFactory factory = (IReportEngineFactory) Platform
      .createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
    birtEngine = factory.createReportEngine(config);
    imageFolder = System.getProperty("user.dir") + File.separatorChar + reportsPath + imagesPath;
    loadReports();
}

もう必要なくなったら、破壊することができます。

@Override
public void destroy() {
    birtEngine.destroy();
    Platform.shutdown();
}

8.2. 出力フォーマットの実装

BIRTは、すでに複数の出力形式をサポートしています。たとえば、 HTML、PDF、PPT、ODTなどです。

サンプルプロジェクトでは、メソッドgeneratePDFReportおよびgenerateHTMLReportを使用してそれらの2つを実装しました。

これらは、出力形式や画像ハンドラーなど、必要な特定のプロパティによってわずかに異なります。

実際、PDFは画像をテキストと一緒に埋め込みますが、HTMLレポートは画像を生成したり、リンクしたりする必要があります。

したがって、PDFレンダリング機能は非常に簡単です

private void generatePDFReport(IReportRunnable report, HttpServletResponse response, 
  HttpServletRequest request) {
    IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report);
    response.setContentType(birtEngine.getMIMEType("pdf"));
    IRenderOption options = new RenderOption();
    PDFRenderOption pdfRenderOption = new PDFRenderOption(options);
    pdfRenderOption.setOutputFormat("pdf");
    runAndRenderTask.setRenderOption(pdfRenderOption);
    runAndRenderTask.getAppContext().put(EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, request);

    try {
        pdfRenderOption.setOutputStream(response.getOutputStream());
        runAndRenderTask.run();
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        runAndRenderTask.close();
    }
}

HTMLレンダリング機能にはさらに多くの設定が必要ですが:

private void generateHTMLReport(IReportRunnable report, HttpServletResponse response, 
  HttpServletRequest request) {
    IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report);
    response.setContentType(birtEngine.getMIMEType("html"));
    IRenderOption options = new RenderOption();
    HTMLRenderOption htmlOptions = new HTMLRenderOption(options);
    htmlOptions.setOutputFormat("html");
    htmlOptions.setBaseImageURL("/" + reportsPath + imagesPath);
    htmlOptions.setImageDirectory(imageFolder);
    htmlOptions.setImageHandler(htmlImageHandler);
    runAndRenderTask.setRenderOption(htmlOptions);
    runAndRenderTask.getAppContext().put(
      EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, request);

    try {
        htmlOptions.setOutputStream(response.getOutputStream());
        runAndRenderTask.run();
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        runAndRenderTask.close();
    }
}

最も注目に値するのは、デフォルトのハンドラーを残す代わりに、HTMLServerImageHandlerを設定したことです。 この小さな違いは、生成されるimgタグに大きな影響を与えます。

  • デフォルトのハンドラーはimgタグをファイルシステムパスにリンクします、多くのブラウザーによってセキュリティのためにブロックされています
  • サーバーURLへのHTMLServerImageHandlerリンク

setImageDirectory メソッドを使用して、エンジンが生成された画像ファイルを保存する場所を指定します。

デフォルトでは、ハンドラーはリクエストごとに新しいファイルを生成するため、キャッシュレイヤーまたは削除ポリシーを追加できます。

8.3. 画像の公開

HTMLレポートの場合、画像ファイルは外部にあるため、サーバーパスからアクセスできる必要があります。

上記のコードでは、 setBaseImageURL メソッドを使用して、 img タグリンクで使用する相対パスをエンジンに指示するため、パスが実際にアクセス可能であることを確認する必要があります!!

このため、 ReportEngineApplication では、imagesフォルダーを公開するようにSpringを構成しました。

@SpringBootApplication
@EnableWebMvc
public class ReportEngineApplication implements WebMvcConfigurer {
    @Value("${reports.relative.path}")
    private String reportsPath;
    @Value("${images.relative.path}")
    private String imagesPath;

    ...

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
          .addResourceHandler(reportsPath + imagesPath + "/**")
          .addResourceLocations("file:///" + System.getProperty("user.dir") + "/" 
            + reportsPath + imagesPath);
    }
}

どのパスを選択する場合でも、ここと前のスニペットの htmlOptions で同じパスが使用されていることを確認する必要があります。そうしないと、レポートで画像を表示できなくなります。

9. レポートの表示

アプリケーションを準備するために必要な最後のコンポーネントは、レンダリングされた結果を返すControllerです。

@RequestMapping(method = RequestMethod.GET, value = "/report/{name}")
@ResponseBody
public void generateFullReport(HttpServletResponse response, HttpServletRequest request,
  @PathVariable("name") String name, @RequestParam("output") String output) 
  throws EngineException, IOException {
    OutputType format = OutputType.from(output);
    reportService.generateMainReport(name, format, response, request);
}

output パラメーターを使用すると、ユーザーが希望の形式(HTMLまたはPDF)を選択できるようになります。

10. レポートのテスト

ReportEngineApplicationクラスを実行してアプリケーションを起動できます。

起動時に、 BirtReportService クラスは、にあるすべてのレポートをロードします / reports フォルダ。

レポートの動作を確認するには、ブラウザで次の操作を行う必要があります。

  • / report / csv_data_report?output = pdf
  • / report / csv_data_report?output = html
  • / report / static_report?output = pdf
  • / report / static_report?output = html

csv_data_reportレポートの外観は次のとおりです。

デザインファイルを変更した後にレポートをリロードするには、ブラウザで / report/reload。を指定するだけです。

11. 結論

この記事では、BIRTをSpring Bootと統合し、落とし穴と課題だけでなく、そのパワーと柔軟性についても説明しました。

この記事のソースコードは、GitHubから入手できます。