GrapeCity.devlog

グレープシティ株式会社のDeveloper Tools〈開発支援ツール〉の最新情報をお届けします。製品のTIPSや発売情報、イベントのお知らせなどをいち早く発信中です。

Spring BootにHTML5ビューワを組み込んで帳票を表示する

ActiveReportsを組み込んで構築したシステムのリプレイス先がLinux + Javaなど、.NET以外のプラットフォームとなるケースが少なからずあると思いますが、その際に帳票部分を別のツールで一から作り直すのはかなりの工数がかかることになるかと思います。

バージョン9.0Jで追加されたJavaScriptライブラリ「HTML5ビューワ」を使用すれば、.NET環境で生成したActiveReportsの帳票を、.NET以外のWebアプリケーション上に簡単に表示させることができるので、既存のActiveReports帳票資産の活用、また追加の帳票の要件があった場合でも、新たな帳票ツールを使うことによる学習コストの削減、といった効果が期待できます。

今回は一例として、JavaのWebアプリケーションフレームワークの定番、「Spring Boot」でHTML5ビューワを組み込んだアプリケーションを作成し、Linuxの環境にデプロイして実行する手順をご紹介したいと思います。

大前提

前述の通り、大前提としてActiveReportsで帳票データを生成するには、.NET Frameworkの環境が必要です。Linux上にデプロイしたSpring Bootのアプリケーションと連携するには、以下の図のようにアプリケーションサーバーと、レポートの配信を行うWebサービスを配置したレポートサーバーを、それぞれ別で用意するような構成にする必要があります。

f:id:GrapeCity_dev:20171221164302p:plain:w450

ただActiveReportsもバージョン11.0J のSP2からPaaS(Microsoft Azure Web Apps)での運用に対応していますので、環境構築自体は難しくないでしょう。

ActiveReports for .NET - 必要システム

レポートサーバーの設定

◆開発環境
Visual Studio 2017

Webサービスの作成

まずはレポートサーバー側にWebサービスの配置を行います。といっても製品にあらかじめ含まれているものを配置するだけです。Visual Studio を開き、 「Visual C#」⇒「Web」のテンプレートから「ASP.NET Web アプリケーション(.NET Framework)」⇒「空」のテンプレートを選択します。プロジェクト名は「ReportService」とします。
f:id:GrapeCity_dev:20171220152500p:plain:w450

f:id:GrapeCity_dev:20171220152517p:plain:w450
作成されたプロジェクトを右クリックして、「追加」⇒「新しい項目」を選択し、「Reporting」から「ActiveReports 11.0J Webサービス」を追加します。このWebサービスが、HTML5ビューワのレポートデータの供給元となります。

f:id:GrapeCity_dev:20171220152717p:plain:w450

ライセンスファイルの作成

プロジェクト内の「Properties」を右クリックして、「追加」⇒[新しい項目]を選択して「licenses.licx」という名前でテキストファイルを追加し、以下のように記述します。

licenses.licx

GrapeCity.ActiveReports.SectionReport, GrapeCity.ActiveReports.v11
GrapeCity.ActiveReports.Export.Pdf.Section.PdfExport, GrapeCity.ActiveReports.Export.Pdf.v11
GrapeCity.ActiveReports.Web.WebViewer, GrapeCity.ActiveReports.Web.v11

CSVファイルの作成

次にレポート内で使用するデータソースを準備します。今回はCSVファイルを使用してみたいと思います。以下のCSVを作成し、プロジェクトに追加しておきます。エンコードは「UTF-8」を指定してください。

Products_drink.csv

"ProductID","ProductName","QuantityPerUnit","UnitPrice"
1,"果汁100% オレンジ","350ml×50本",200
2,"果汁100% グレープ","350ml×50本",200
3,"果汁100% レモン","250ml×50本",1000
4,"果汁100% ピーチ","250ml×20本",1000
5,"コーヒーマイルド","250ml×20本",1000

レポートファイルの作成

次にレポートファイルを作成します。今回はActiveReportsの販売当初から提供している、コード形式のセクションレポートを使用します。プロジェクトを右クリックして、「追加」⇒「新しい項目」を選択し、「Reporting」から「ActiveReports 11.0J セクションレポート(コード)」を追加します。

f:id:GrapeCity_dev:20171220153015p:plain:w450

追加されたSectionReport1.csをデザイン画面で開き、レポートをデザインしていきます。detailセクションにデータを表示するTextBoxを4つ並べます。

f:id:GrapeCity_dev:20171220171940p:plain:w450

デザイナ上のグレーの領域をダブルクリックすると、コードビハインドにReportStartイベントの処理が作成されるので、以下のコードを追加します。

SectionReport1.cs

private void SectionReport1_ReportStart(object sender, EventArgs e)
{
    var ds = new GrapeCity.ActiveReports.Data.CsvDataSource();
    //  CSVファイルの絶対パスを指定。後で書き換えます。
    string csvpath = @"C:\Users\hoge\Documents\Visual Studio 2017\Projects\ReportService\ReportService\Products_drink.csv";
    string con = "Path=" + csvpath + ";Locale=ja-JP;TextQualifier=\";ColumnsSeparator=,;RowsSeparator=\\r\\n;HasHeaders=True";
    ds.ConnectionString = con;
    DataSource = ds;

    // テキストボックスにフィールドを設定する
    textBox1.DataField = "ProductID";
    textBox2.DataField = "ProductName";
    textBox3.DataField = "QuantityPerUnit";
    textBox4.DataField = "UnitPrice";
}

接続文字列やレポートの表示項目をアプリ側から入力した値に応じて動的に変更したい場合、パラメータを使用することができます。今回は単純にWebアプリ側から取得した値をレポート上に表示させてみます。レポートエクスプローラーから「パラメータ」のノードを右クリック ⇒ 「追加」をクリックし、「from_webapp」という名前のパラメータを追加します。この時、実行時にパラメータ入力のダイアログが表示されないよう、PromptUser プロパティの値を"False"にしておいてください。

f:id:GrapeCity_dev:20171220172656p:plain:w450

追加されたノードをpageHeaderセクションにドラッグ&ドロップします。これでパラメータと関連付いたテキストボックスが作成されます。あとは適当に帳票のタイトルのラベルやフォントなどの調整を行います。

f:id:GrapeCity_dev:20171220173338p:plain:w450

この時点でデザイナのプレビュータブをクリックしてプレビューするとこのようになります。パラメータを設定したテキストボックスにはまだ何も表示されません。

f:id:GrapeCity_dev:20171220173629p:plain:w450

Web Apps へのデプロイ

ここまででWebサービスとレポートの作成は完了なので、あとはサーバーにデプロイします。その前にSectionReport1.csのコードビハインドで、サーバーへデプロイ後もCSVファイルのパスが取得できるよう、コードを以下のように書き換えておきます。

SectionReport1.cs

string csvpath = System.Web.HttpRuntime.AppDomainAppPath + "Products_drink.csv";

今回はWebサービスの運用環境として、Microsoft Azure Web Appsを使用します。Visual Studio上でウィザードからデプロイできるので非常に簡単です。

プロジェクトを右クリックして「発行」メニューを選択し、表示されるダイアログで「Microsoft Azure App Service」⇒「新規作成」を選択して「発行」ボタンをクリックします。

f:id:GrapeCity_dev:20171221102633p:plain:w450

App Serviceの作成画面が表示されますが、まずはApp Serviceプランの作成を行い、リージョンや料金プランの設定を行います。今回はデプロイ先を「Japan East」、サイズを「B1」にしています。

f:id:GrapeCity_dev:20171221104426p:plain:w450

あとはアプリ名やリソースグループの設定を行い「作成」をクリックするとデプロイが始まります。

f:id:GrapeCity_dev:20171221104439p:plain:w450

以上でWebサービスのデプロイ作業は完了です。ブラウザから「http://App ServiceのURL/ActiveReports.ReportService.asmx」にアクセスし、以下のような画面が表示されればOKです。

f:id:GrapeCity_dev:20171221104904p:plain:w450

Spring Bootアプリケーションの作成

次にSpring Bootアプリケーションを作成します。以下の開発環境を構築し、「Hello World」の表示レベルのアプリが動かせるようになっていることを前提としています。

◆開発環境
Eclipse 4.7 Oxygen
Java 9
STS プラグイン 3.9.1

Eclipseを開き、「ファイル」⇒「新規」⇒「その他」を開き、「Spring Boot」⇒「Spring スターター・プロジェクト」をクリックします。

f:id:GrapeCity_dev:20171221110259p:plain:w450

名前と成果物をそれぞれ「Html5VDemo」、グループとパッケージをそれぞれ「com.Html5VDemo」に設定します。Javaのバージョンは環境に合わせて、他はデフォルトの設定のままにして進みます。

f:id:GrapeCity_dev:20171221110427p:plain:w450

依存関係に「Web」を追加し完了です。

f:id:GrapeCity_dev:20171221110505p:plain:w450

静的ファイルの配置

src/main/resources/static フォルダの下に「css」、「i18n」、「Scripts」のフォルダをそれぞれ作成し、HTML5ビューワの表示に必要な以下のJSやCSSなどの静的ファイルをコピーします。これらのファイルは製品のインストールフォルダの配下(...\ActiveReportsNET11\Deployment\Html)より取得できます。

f:id:GrapeCity_dev:20171221110611p:plain:w450

  • css/GrapeCity.ActiveReports.Viewer.Html.css
  • i18n/ja.txt
  • Scripts/GrapeCity.ActiveReports.Viewer.Html.js

Thymeleaf テンプレートの作成

次にThymeleafでテンプレートを作成し(Spring MVC ならJSP)、HTML5ビューワを組み込んでいきます。最初にpom.xmlに以下の依存性を追加します。

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

src/main/resources/templates フォルダの下にHtml5Viewer.htmlを作成し、以下のように記述します。

Html5Viewer.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="html5view">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <link rel="stylesheet" href="css/GrapeCity.ActiveReports.Viewer.Html.css" />
</head>
<body>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js" type="text/javascript"></script>
    <script src="Scripts/GrapeCity.ActiveReports.Viewer.Html.js" type="text/javascript"></script>
    <button type="button" onclick="RenderReport()" style="margin:20px">表示</button>
    <div id="viewer" style="width:1200px;height:900px;margin:0px 0px 0px 20px"></div>

    <script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
    function RenderReport() {
                var viewer = GrapeCity.ActiveReports.Viewer(
                {
                    element: '#viewer',
                    report: {
                        // セクションレポートのクラスの完全名を指定します。
                       id: "ReportService.SectionReport1",
                        // レポートファイルに渡すパラメータの設定
                       parameters: [
                           {
                           name: 'from_webapp',
                           value: /*[[${osname}]]*/
                           }]
                    },
                    reportService: {
                       // Azureに配置したWebサービスのURL
                        url: 'https://App ServiceのURL/ActiveReports.ReportService.asmx'
                    },
                    uiType: 'desktop',
                    // 日本語のリソースファイルのパスを指定します。
                    localeUri: 'i18n/ja.txt',
                });
       };
    /*]]>*/
    </script>
</body>
</html>

Controllerの作成

/src/main/java/com/Html5VDemoの配下にControllerを追加します。名前はHtml5ViewerControllerとします。addAttributeで帳票のパラメータとして渡す文字列を設定しています。今回はアプリは実行された環境のOS名とバージョン情報を渡してみます。

Html5ViewerController.java

package com.Html5VDemo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller

public class Html5ViewerController {
    @GetMapping("/Html5Viewer")
    public String Html5Viewer(Model model) {
        model.addAttribute("osname","OS:" + System.getProperty("os.name").toLowerCase() + " Version:"+ System.getProperty("os.version").toLowerCase());
        return "Html5Viewer";
    }
}

TemplateResolverの設定

同じ場所にTemplateResolverの設定用のクラスを作成します。名前はThymeleafConfigurerとします。

ThymeleafConfigurer.java

package com.Html5VDemo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Configuration
public class ThymeleafConfigurer extends WebMvcConfigurerAdapter {

    @Bean
    @Description("Thymeleaf template resolver serving HTML 5")
    public ClassLoaderTemplateResolver templateResolver() {

        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();

        templateResolver.setPrefix("templates/");
        templateResolver.setCacheable(false);
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML5");
        templateResolver.setCharacterEncoding("UTF-8");

        return templateResolver;
    }
    @Bean
    @Description("Thymeleaf template engine with Spring integration")
    public SpringTemplateEngine templateEngine() {

        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());

        return templateEngine;
    }

    @Bean
    @Description("Thymeleaf view resolver")
    public ViewResolver viewResolver() {

        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();

        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setCharacterEncoding("UTF-8");

        return viewResolver;
    }
}

アプリケーションの実行

以上でアプリケーションの作成は完了なので実行してみます。右クリックから「実行」⇒「Spring Boot アプリケーション」をクリックします。Spring Bootでは組み込みのTomcatが使えるのでこれだけで実行できます。

f:id:GrapeCity_dev:20171221115715p:plain:w450

アプリケーションが起動したら、ブラウザから「http://localhost:8080/Html5Viewer」にアクセスします。以下のような画面が表示されるので、「表示」ボタンをクリックして、HTML5ビューワの初期化処理を呼び出します。

f:id:GrapeCity_dev:20171221120423p:plain:w450

HTML5ビューワのツールバーは表示されましたがエラーになりました。

f:id:GrapeCity_dev:20171221135125p:plain:w450

開発者ツールなどで見てみると、以下のようなエラーが出ています。

f:id:GrapeCity_dev:20171221135346p:plain:w450

今回はローカルホストのアプリと、Azure上のWebサービスでクロスドメイン通信が発生しますが、Webサービス側でCORSの設定を行っていませんでした。これは製品ヘルプにも記載のある既知の事象です。

ActiveReportsユーザーガイド - CORSを使用した異なるドメインからのレポートの表示

Web AppsならダッシュボードなどからCORSの設定は可能かと思いますが、今回は製品ヘルプに記載のグローバルアプリケーションクラスを使用する方法で対応します。

「ReportService」のプロジェクトを開き、プロジェクトを右クリック⇒「追加」⇒「新しい項目」を選択し、グローバルアプリケーションクラスを追加します。

f:id:GrapeCity_dev:20171221141024p:plain:w450

製品ヘルプに従い、Application_BeginRequestメソッドを以下のように変更します。

Global.asax.cs

protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
  "GET, POST, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
  "Content-Type, Accept");
        HttpContext.Current.Response.End();
    }
}

あとは「ReportService」を再度Azureにデプロイします。先ほどのデプロイ処理でプロファイルができているのでワンクリックで済みます。デプロイ完了後、再度実行すれば以下のようにSpring Bootのアプリケーションに組み込んだHTML5ビューワ上にActiveReportsの帳票が表示されます。青字で表示されているのは、先ほどControllerから渡したOSの情報です。

f:id:GrapeCity_dev:20171221143142p:plain:w450

CentOSへのデプロイ

最後の仕上げとして、Linux環境へのデプロイを行います。環境はMicrosoft AzureでCentOSのイメージを使用して作成した仮想マシンを使用します。あらかじめJavaはインストール済みです。

jarファイルの作成

デプロイするjarファイルを作成します。右クリックから「実行」⇒「Maven Install」をクリックします。

f:id:GrapeCity_dev:20171221154114p:plain:w450

ビルドが成功すると「target」フォルダの配下にjarファイルが作成されるので、このファイルをFTPクライアントなどを使用してCentOSの環境にコピーします。前述の通り、Tomcatは組み込みのものを使用するので、コピー先はよほど変な場所でなければ大丈夫(なはず)です。

f:id:GrapeCity_dev:20171221154438p:plain

実行結果

PuTTYなどのリモートログオンクライアントでCentOSの環境にログインし、jarファイルをコピーしたディレクトリに移動して以下のコマンドを実行し、アプリケーションを起動します。

java -jar Html5VDemo-0.0.1-SNAPSHOT.jar

起動が完了したらブラウザで「http://仮想マシンのホスト名:8080/Html5Viewer」にアクセスします。ローカル環境で実行したときと同様にHTML5ビューワで帳票が表示され、パラメータで渡した青字のOSのバージョン情報もちゃんとLinuxのものになっています。

f:id:GrapeCity_dev:20171221162200p:plain:w450