Jasper Reports でJavaのBeanクラスのフィールドから値を取得してPDFに出力する。

変更履歴：
(2015/02/16)
・見出し名を修正
・complieJasperReportsの無意味なInputStream表記を削除
・日本語文言の表示には、別の設定が必要なので、サンプルの文字列を修正しましたm(_ _)m
・「日本語の文字列を表示するには」を追記しました。

(2015/02/19)
・JasperReportsのスクリーンキャプチャ追加

(2015/06/19)
・「jasperファイルへのコンパイルとフォントサイズについて」を追記


# 目的

JavaBeanクラスに格納した値を、JasperReportsで帳票出力する方法。

例えば、以下のようなDtoに入れた値を、JasperReportsのTextFieldコンポーネントに出力したいとする。

```java:FamilyDto
public class FamilyDto{

 private String address;
 private String phone;
 
 //上記フィールドのsetter/getter
 ...

}
```

# Jrxml：Java Beanの値を表示する設定手順


※以下は、Jaspersoft Studioでの操作方法。

１：jrxmlを作る。（データセット等の設定は無関係なので、作成時のオプションはデフォルトのままでOK）

２：Outlineビューで、ツリーの最上位要素（jrxmlファイル名と同じ）を右クリックする。（※図１）

--右クリックメニューが表示される（※図１）

３：右クリックメニューの、「Dataset And Query...」を選択する。（※図１）

図１：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/de69498a-de26-35f6-1367-dfb16d47fc46.png)

--Dataset And Queryダイアログが表示される

４：表示されたダイアログ上で「JavaBeans」タブを選ぶ（※図２）

図２：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/1a9318e2-29ed-11f8-7657-4ec3794b7ce2.png)

５：下部の「Add」ボタンを押下し、Beanクラスのフィールドに対応した下記フィールドを追加する。（図３～図５）
・address(Class Typeにはjava.lang.Stringを指定)
・phone(Class Typeにはjava.lang.Stringを指定)

図３：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/823ce535-19ed-0380-9989-47248737123b.png)

図４：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/35abcab2-b725-1c51-2e06-4dc2813f43af.png)

図５：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/5d1e8e9e-aad9-360c-42be-914513da8093.png)


※Class Nameの横にある「...」ボタンからクラスを参照してフィールド一括取込もできるが、
プロジェクトのビルドパスに対象のBeanクラスが追加されている必要があるので、
その設定が面倒（もしくは上手く行かない）場合は、手打ちでフィールド名を書いてもちゃんと動きます。
必要なのはフィールド名とフィールドの型だけで、そのフィールドがどのクラスのメンバかの情報は不要です。

６：Paletteビューから、Text Fieldをドラッグ＆ドロップする。（※図６）

図６：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/83c74522-60a1-cbfb-7683-3c4290e0e2cc.png)


７：ドロップしたTextFieldをダブルクリックする。（※図７）

--Expression Editorダイアログが表示される。（※図７）

図７：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/d9c87601-088c-e70c-3d15-283375b75b2e.png)


８：ダイアログの上部のテキスト入力エリアに入っている初期値を削除する。（※図８）

９：ダイアログの下部の3ペインのうち、左端のペインでFieldsを選択する。（※図８）

--真ん中のペインに、５で登録したフィールドがリストアップされる（※図８）

図８：
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/bf4352e4-f702-a67b-2fa0-5cd179c84954.png)


１０：ダイアログの下部真ん中のペインで、表示したいフィールドをダブルクリック。（※図９）

※図９:
![image](https://qiita-image-store.s3.amazonaws.com/0/34570/5b1b7508-4f38-3839-ca16-b10efeca9db7.png)


１１：Finishボタンでダイアログを閉じる。

※JasperReportsのPDF出力で日本語の文字列を表示するには、日本語フォントの設定が必要です。
『日本語の文字列を表示するには』の項目を参照してください。
（サンプルとして英数を出力するだけで良ければ、jrxml側の設定手順はこれでおしまいです）

１２：保存して、Build Allボタンでjasperファイルを生成する。
（※ここでビルドしなくてもJava側で動的にコンパイルもできます）

# jasperファイルへのコンパイルとフォントサイズについて

※特に理由が無ければ、Jaspersoft Studioではjrxmlファイルのみを作成し、jasperファイルへのコンパイルは下記のコードのようにjava側で行った方がいいかもしれません。
原因は判りませんが、複数の環境で、
「Jaspersoft Studioでコンパイルしたjasperファイルを使うと、指定したフォントサイズ（や太文字などのオプション）が適用されない（全て同じフォントサイズになる）」
という現象が起こりました。
java側でJasperCompileManager # compileReportToFileメソッドを使ってコンパイルしたjasperファイルでは、
そういった現象には遭遇していません。


# Java側の書き方

※ちょっと前の記憶を掘り起こしてるので、どっか間違ってたらツッコミ下さい。

１３：pom.xmlにjasper関連の依存関係を書く

```xml:pom.xml
	<repositories>
		<repository>
			<id>maven.jasper.org</id>
			<name>Jasper Maven Repository</name>
			<url>http://jasperreports.sourceforge.net/maven2/</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<dependencies>
		<dependency>
			<groupId>net.sf.jasperreports</groupId>
			<artifactId>jasperreports</artifactId>
			<version>5.6.1</version>
		</dependency>
	</dependencies>
```

１４：ソースコードを書く


```java:MyCreatePdf.java
	
	void createPdf(){

		MyJasperGenerator gen = new MyJasperGenerator();

		//表示するデータを作る
		FamilyDto dto = new FamilyDto();

		//日本語を表示する場合は、別の設定が必要です。サンプルは英数字で確認してください。
		dto.setAddress("Tokyo HogeHoge PiyoPiyo");
		dto.setPhone("123-456-7890");

		//JRDataSourceに詰める
		JRDataSource dataSource = gen.makeBeansDataSource(dto);

		//１で作ったjrxmlファイルのパス
		String jrxmlFilePath = "...○○.jrxml";

		//jrxmlからコンパイルするjasperファイルの出力先
		String jasperFilePath= "...○○.jasper";

		//作成するpdfファイルの出力先
		String outputPdfPath= "...××.pdf";

		Map<String,Object> params = new HashMap<String,Object>();//とりあえず今回は使いません。


		//作成実行
		gen.outputPdf(jrxmlFilePath, jasperFilePath, params, dataSource, outputPdfPath);
	}

```

```java:MyJasperGenerator.java

	/**
	 * BeanをJRDataSourceに変換する
	 *
	 * @param dataSourceBean
	 * @return
	 */
	public JRDataSource makeBeansDataSource(Object dataSourceBean) {

		List<?> dataSourceList = Arrays.asList(dataSourceBean);
		JRDataSource res = new JRBeanCollectionDataSource(dataSourceList);
		return res;
	}
	/**
	 * jasperReportsを使用してjdfファイルを作成する。
	 *
	 * @param jrxmlFilePath 
	 * @param jasperFilePath 
	 * @param params 
	 * @param dataSource 
	 * @param destPath 
	 */
	public void outputPdf(
			String jrxmlFilePath,
			String jasperFilePath,
			Map<String,Object> params,
			JRDataSource dataSource,
			String outputPdfPath){

		if(!new File(jasperFilePath).exists()) {
			//jrxmlファイルをコンパイルする。
			complieJasperReports(jrxmlFilePath, jasperFilePath);
		}

		try{

		   	//抽象レポートを生成する。
			JasperPrint basePrint = JasperFillManager.fillReport(jasperFilePath, params, dataSource);
			//PDFファイルに出力する。
			JasperExportManager.exportReportToPdfFile(basePrint, outputPdfPath);
   		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}

	/**
	 * jrxmlファイルをコンパイルする。
	 *
	 * @param jrxmlFilePath
	 * @param jasperFileName
	 */
	private void complieJasperReports(String jrxmlFilePath,String jasperFileName){

		//jrxmlファイルを読み込む
		try {
			//コンパイル実行
			JasperCompileManager.compileReportToFile(jrxmlFilePath,jasperFileName);

		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}

```

# 日本語の文字列を表示するには

ClassMethodさんの以下の記事の通りにやったら、日本語は表示できました。

http://dev.classmethod.jp/server-side/java/jasperreports-tutorial/

上記の記事ではゴシック文字のipaexg.ttfを使用した設定のみ行っていますが、
明朝も使いたい、という場合は、
ipaexm.ttfも取得し、ipaexgと同様に設定すれば、上手く行きます。（Family Nameは、ipaexmとすればいいでしょう）

Java側については、ipaex.xml以外にipaexm.xmlも作り、
ipaexm.ttfと共にfontsフォルダに配置します。

```xml:ipaexm.xml
<?xml version="1.0" encoding="UTF-8"?>
<fontFamilies>
  <fontFamily name="ipaexm">
    <normal>fonts/ipaexm.ttf</normal>
    <pdfEncoding>Identity-H</pdfEncoding>
    <pdfEmbedded>true</pdfEmbedded>
  </fontFamily>
</fontFamilies>
```

jasperreports_extension.propertiesファイルに以下の一行を追加します。

```properties:jasperreports_extension.properties
net.sf.jasperreports.extension.simple.font.families.ipaexm=fonts/ipaexm.xml
```

以上で、ゴシックはipaex、明朝はipaexmという名前で指定できるでしょう。