JasperReportsを使うときのライブラリについて

クラスメソッド様のブログにはいつもお世話になっております。

dev.classmethod.jp

2013年に出たブログですが、今でもたまにたどり着くこのページ。 依存ライブラリの部分がmavenだと若干古くなっているようなのでメモとして残しておく。

JasperReports LibraryはPDFを出力する場合にitextを利用しますが、この時に依存しているバージョンはLGPLである2.1系の最新バージョンである2.1.7にJasperReportsで独自のパッチを当てた、2.1.7.js2です。このバージョンはMavenのcentral repositoryに存在しないため、Jaspersoftのリポジトリを追加しなければなりません。

最新版(6.4.1)だと itext-2.1.7.js6 がMavenのcentral repositoryに存在するようで、リポジトリの追加は不要。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>hanbai.nii</groupId>
    <artifactId>test1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>test1</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javac.target>1.7</javac.target>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports -->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.4.1</version>
        </dependency>
    </dependencies>
</project>

このページを参考に依存関係を確認する。

d.hatena.ne.jp

確認結果は以下の通り。

[INFO] xxxx.xxxx:test1:jar:0.0.1-SNAPSHOT
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] \- net.sf.jasperreports:jasperreports:jar:6.4.1:compile
[INFO]    +- commons-beanutils:commons-beanutils:jar:1.9.3:compile
[INFO]    +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO]    +- commons-digester:commons-digester:jar:2.1:compile
[INFO]    +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO]    +- com.lowagie:itext:jar:2.1.7.js6:compile
[INFO]    |  \- org.bouncycastle:bcprov-jdk15on:jar:1.52:compile
[INFO]    +- org.jfree:jcommon:jar:1.0.23:compile
[INFO]    +- org.jfree:jfreechart:jar:1.0.19:compile
[INFO]    +- org.eclipse.jdt.core.compiler:ecj:jar:4.3.1:compile
[INFO]    +- org.codehaus.castor:castor-xml:jar:1.3.3:compile
[INFO]    |  +- org.codehaus.castor:castor-core:jar:1.3.3:compile
[INFO]    |  +- commons-lang:commons-lang:jar:2.6:compile
[INFO]    |  +- javax.inject:javax.inject:jar:1:compile
[INFO]    |  +- stax:stax:jar:1.2.0:compile
[INFO]    |  |  \- stax:stax-api:jar:1.0.1:compile
[INFO]    |  \- javax.xml.stream:stax-api:jar:1.0-2:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-core:jar:2.1.4:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-databind:jar:2.1.4:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-annotations:jar:2.1.4:compile
[INFO]    +- org.apache.lucene:lucene-core:jar:4.5.1:compile
[INFO]    +- org.apache.lucene:lucene-analyzers-common:jar:4.5.1:compile
[INFO]    +- org.apache.lucene:lucene-queryparser:jar:4.5.1:compile
[INFO]    |  +- org.apache.lucene:lucene-queries:jar:4.5.1:compile
[INFO]    |  \- org.apache.lucene:lucene-sandbox:jar:4.5.1:compile
[INFO]    |     \- jakarta-regexp:jakarta-regexp:jar:1.4:compile
[INFO]    +- org.olap4j:olap4j:jar:0.9.7.309-JS-3:compile
[INFO]    +- com.google.zxing:core:jar:3.2.1:compile
[INFO]    \- com.ibm.icu:icu4j:jar:57.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 53.129 s
[INFO] Finished at: 2017-08-18T10:41:44+09:00
[INFO] Final Memory: 14M/64M
[INFO] ------------------------------------------------------------------------

以上。

SXSSFWorkbookの不具合 #apachePoi

qiita.com

知らなかったので再現プログラムを書いてみた。

import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class WriteTest {

    public static void main(String[] args) {

        String outputFilePath = "out.xlsx";
        Workbook book = null;
        FileOutputStream fout = null;

        try {
            book = new SXSSFWorkbook();

            Font font = book.createFont();
            font.setFontName("MS ゴシック");
            font.setFontHeightInPoints((short) 9);

            CellStyle style = book.createCellStyle();
            style.setWrapText(true);

            Sheet sheet = book.createSheet();

            Row row = sheet.createRow(0);
            Cell cell0 = row.createCell(0);
            cell0.setCellValue("aaa\r\nbbb");
            cell0.setCellStyle(style);

            Cell cell1 = row.createCell(1);
            cell1.setCellValue("aaa\rbbb");
            cell1.setCellStyle(style);

            Cell cell2 = row.createCell(2);
            cell2.setCellValue("aaa\nbbb");
            cell2.setCellStyle(style);

            Cell cell3 = row.createCell(3);
            cell3.setCellValue("aaa\\nbbb");
            cell3.setCellStyle(style);
            
            fout = new FileOutputStream(outputFilePath);
            book.write(fout);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                book.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

処理結果はこうなり、A1セルの改行が2回行われていることが確認出来る。

f:id:su_zu_ki_1010:20170818100746p:plain

原因となるコードはpoi-ooxml-3.xx.jarの org.apache.poi.xssf.streaming.SheetDataWriter.javaの371行目から379行目の部分。 ※3.17-beta1でも直っていないことを確認した。

// Special characters
case '\n':
case '\r':
    if (counter > last) {
        _out.write(chars, last, counter - last);
    }
    _out.write("&#xa;");
    last = counter + 1;
    break;

#xa;はxml文書で改行コードを表すらしい。

www.4d.com

当面の対応は、\r\nを\r、あるいは\nに置換するしかなさそうだけど、本対応はapacheにバグレポートを書くことだろうなぁ。 githubだったらissueに書けばいいんだろうけど、apache poiはsubversionで活動されているので報告先がわからない…。

というか、SXSSFWorkbookってあまり使われていないのかな。

今日学んだことの覚書

TeraTermマクロでウィンドウサイズを変える

dispstr #$1b"[8;42;130t"

42と130は任意の数字にする。

srad.jp

DB2をインストール後、5005エラーが出る時の対処法

db2systray -clean

このコマンドを打てばいいのだけど、OSによってはそれでも5005エラーが出る。 その時は、コマンドプロンプト管理者権限で開いて実行すればよい。

www-01.ibm.com

Linuxコマンドメモ<find+grepの組み合わせ>

コマンド

find ./* -newermt '20170803 08:00' | xargs grep 検索ワード

これで2017/8/3の8時以降に更新されたファイルの中から、検索ワードが存在するファイルのみを抽出できる。

参考

findで具体的な日付、時間で検索するnewerXYオプション - システム開発メモ

d.hatena.ne.jp

rfs.jp

Eclipse Oxygenをダウンロードしたい

eclipse.org トップページのDONLOWADを踏むとインストーラがダウンロードされてしまう。

そんなんじゃなくて、従来の色々なバージョンのeclipseが選択できる画面からダウンロードしたいんだ!
そんな人向け。

eclipse.org

遷移方法は トップページを開く
 ↓
「GETTEING STARTED」 をクリック
 ↓
「DONLOWAD ECLIPSE IDE」 のボタンをクリック
 ↓
薄く出ている、「Download Packages」のリンクをクリック
 ↓
慣れ親しんだページに遷移できる。

"10年の長きに渡り Java の可変長引数を過信していた話"を読んで確認した

etc9.hatenablog.com

恥ずかしながら、自分も過信していたのでこのブログを読んで確認してみた。

public class 可変長引数テスト {
    
    public static void main(String... args) {

        new 可変長引数テスト().method();
        new 可変長引数テスト().method("hello");
        new 可変長引数テスト().method("hello", "world");

        String str = "hello";
        new 可変長引数テスト().method(str);

        str = null;
        new 可変長引数テスト().method(str);

        new 可変長引数テスト().method(null);

        new 可変長引数テスト().method((String) null);

        new 可変長引数テスト().method((String[]) null);

    }

    public void method(String... args) {

        System.out.println("*-*-*-*-*-");

        try {
            for (String string : args) {
                System.out.println(string);
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

    }
}

eclipseだと、

new 可変長引数テスト().method(null);

この行で以下のような警告文が表示される。(java1.7だと以下の文章)

タイプ null の引数は、タイプ 可変長引数テスト からの可変引数メソッド method(String…) の呼び出しに対しては String へ明示的にキャストする必要があります。あるいは、可変引数呼び出しに対しては String へキャストすることもできます

  1. コンパイラがこのような警告を吐く記述はちょっと疑うようにした方がいい。
  2. わかりました、ということでStringに明示的にキャストしても、元の記事にあるようにぬるぽで落ちる。
    nullを明示的に渡したいときはStringにキャストしないといけない。

普段意識したことが無かったので、勉強になった。

数年後の自分がこのブログにたどり着くことが無いといいな。

鹿児島から北海道まで全部の新幹線に乗って移動できるのか

調べてみた。

※参考 新幹線路線図 | nippon.com

鹿児島中央駅
↓ 九州新幹線
博多駅
↓ 山陽新幹線
新大阪駅
↓ 東海道新幹線
名古屋駅
↓ JR特急しらさぎ
金沢駅
↓ 北陸新幹線
高崎駅
↓ 上越新幹線
大宮駅
↓ 東北新幹線
福島駅
↓ 山形新幹線
新庄駅
↓ JR奥羽本線
秋田駅
↓ 秋田新幹線
盛岡駅
↓ 東北新幹線(再)
新青森駅
↓ 北海道新幹線
新函館北斗駅

移動の都合上、名古屋駅から金沢駅と、新庄駅から秋田駅までは新幹線以外のルートになるけど、それ以外は新幹線で頑張れる。