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

hakobera's blog

技術メモ。たまに雑談

JAX-RS + Doma で 100% ハマルこと

Doma の Entity を JAX-RS で JSON/XML 化できないという話。

  • Doma がjava.util.Date 使えない
  • JAX-RS が内部で利用している JAXB は java.sql.Date/Timestamp を変換できない

Doma が java.util.Date 使えないのも少しだけ不満なのですが、これは JAXB の問題ですね。

解決方法

Doma の制約は回避方法がないので、JAXB の XMLAdaptor を書いて解決します。

java.sql.Date 用
package adaptor;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class SqlDateAdaptor extends XmlAdapter<java.util.Date, java.sql.Date> {

    @Override
    public Date unmarshal(java.util.Date v) throws Exception {
        return new java.sql.Date(v.getTime());
    }

    @Override
    public java.util.Date marshal(java.sql.Date v) throws Exception {
        return new java.util.Date(v.getTime());
    }
}
java.sql.Timestamp 用
package adaptor;

import java.sql.Date;
import java.sql.Timestamp;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class TimestampAdaptor extends XmlAdapter<java.util.Date, Timestamp> {
    
    @Override
    public Date marshal(Timestamp v) {
        return new Date(v.getTime());
    }
    
    @Override
    public Timestamp unmarshal(java.util.Date v) throws Exception {
        return new Timestamp(v.getTime());
    }

}

これを全ての java.sql.Date フィールドに指定しても良いのだけれど、面倒なのでパッケージに指定します。

Doma の Entity を置いてあるパッケージに package-info.java を作成して以下のようにアノテーションを書きます。

package-info.java
@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(value = adaptor.SqlDateAdaptor.class, type = java.sql.Date.class),
    @XmlJavaTypeAdapter(value = adaptor.TimestampAdaptor.class, type = java.sql.Timestamp.class)
})
package entity;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

さらっと書いてるけど、実際は3時間くらいハマッてました。