読者です 読者をやめる 読者になる 読者になる

HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

Simpleライブラリの検証(5)

ざっくりと試してみたSimpleライブラリ。

いろいろと気になる点もあったので、ざくっと検証してみる。の続き。

値の解析エラーの扱い

たとえば、POJOではshort型として定義されているフィールドに対応する値が"123456789"だったら、int型として定義されているフィールドに対応する値が"hello"だったら、格納できるわけはないのだが、その場合にどういうエラーが発生するのかしないのか。

とりあえず、例示した2つのケースを試してみる。

まず、次の3つのPOJOを定義する。
Hoge1:ケース1「int⇒short」を試すためのクラス。

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name = "root")
public class Hoge1 {

    @Element(name = "field1")
    public int field1;

}

Hoge2:ケース2「String⇒int」を試すためのクラス。

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name = "root")
public class Hoge2 {

    @Element(name = "field2")
    public String field2;

}

Foo:Hoge1、Hoge2それぞれのフィールドの値を受けるためのクラス。

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root(name = "root")
public class Foo {

    @Element(name = "field1", required = false)
    public short field1;

    @Element(name = "field2", required = false)
    public int field2;

}

そして、ケース1、ケース2を実行するプログラム。

import java.io.File;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        test1();
        test2();
    }

    /**
     * Hoge1.field1 に値をセットする。
     * ⇒readの際に、Foo.field1 に値を格納しようとする。
     */
    private static void test1() {
        System.out.println("=== serialize ===");
        try {
            Serializer serializer = new Persister();
            Hoge1 hoge1 = new Hoge1();
            hoge1.field1 = 123456789;

            File result = new File("data/hoge1.xml");
            System.out.println("      " + result);
            serializer.write(hoge1, result);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        System.out.println("=== deserialize ===");
        try {
            Serializer serializer = new Persister();

            File source = new File("data/hoge1.xml");
            System.out.println("      " + source);
            Foo foo = serializer.read(Foo.class, source);
            dumpFoo(foo);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
    /**
     * Hoge2.field2 に値をセットする。
     * ⇒readの際に、Foo.field2 に値を格納しようとする。
     */
    private static void test2() {
        System.out.println("=== serialize ===");
        try {
            Serializer serializer = new Persister();
            Hoge2 hoge2 = new Hoge2();
            hoge2.field2 = "hello";

            File result = new File("data/hoge2.xml");
            System.out.println("      " + result);
            serializer.write(hoge2, result);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        System.out.println("=== deserialize ===");
        try {
            Serializer serializer = new Persister();

            File source = new File("data/hoge2.xml");
            System.out.println("      " + source);
            Foo foo = serializer.read(Foo.class, source);
            dumpFoo(foo);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }

    private static void dumpFoo(Foo foo) {
        System.out.println("    field1: " + foo.field1);
        System.out.println("    field2: " + foo.field2);
    }

}

そして実行結果。

=== serialize ===
      data\hoge1.xml
=== deserialize ===
      data\hoge1.xml
java.lang.NumberFormatException: Value out of range. Value:"123456789" Radix:10
    at java.lang.Short.parseShort(Short.java:122)
    at java.lang.Short.valueOf(Short.java:153)
    at java.lang.Short.valueOf(Short.java:178)
    at org.simpleframework.xml.transform.ShortTransform.read(ShortTransform.java:57)
(以下省略)
=== serialize ===
      data\hoge2.xml
=== deserialize ===
      data\hoge2.xml
java.lang.NumberFormatException: For input string: "hello"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Integer.parseInt(Integer.java:447)
    at java.lang.Integer.valueOf(Integer.java:553)
    at org.simpleframework.xml.transform.IntegerTransform.read(IntegerTransform.java:57)
(以下省略)

やはり解析エラー(RuntimeException)になる。まぁ当然といえば当然か。不適切なPOJOクラスを指定してデシリアライズしようとするのはプログラムのバグであろうし、データのナローイング変換を暗黙のうちに実施されても困る。

ところで、APIドキュメントを見てみると、org.simpleframework.xml.transform.TransformException という例外クラスがある。このクラスの説明を見る限りでは、上記の解析エラーの際にTransformExceptionが投げられてもよさそうな気がするが、気づいていないだけなのだろうか。(そもそも、Simpleフレームワークの(ほとんど)すべてのメソッドシグネチャが「throws java.lang.Exception」となっている辺り、ちゃんとは考えていないのかなぁという感が否めない‥)