JAX-RSで好きなオブジェクトを返す
今回は使用頻度が高いJAX-RSの機能を解説。
JAX-RSではデフォルトである程度の変換機能はあるが、これを自由に、そして簡単にカスタマイズできる。
今回はjava.util.Propertiesを返すようにしてみよう。
リソース定義。
package jaxrs; import java.util.Properties; import javax.ws.rs.Consumes; import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.Produces; @Path("hoge") public class Hoge { @GET @Produces("text/plain; charset=UTF-8") @Consumes public Properties getProps() { Properties props = new Properties(); props.setProperty("KEY", "VALUE"); props.setProperty("HOGE", "ほげ?"); props.setProperty("ぷろぱてぃ", "めっせーじ"); return props; } }
このままだとPropetiesをどう変換したらよいかわからないのでそれを教えてあげる。MessageBodyWriterを実装したクラスを作るとよい。
package jaxrs; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Properties; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; @Provider public class PropertyWriter implements MessageBodyWriter<Properties>{ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type.equals( Properties.class ); } public long getSize(Properties t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } public void writeTo(Properties t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { Writer writer = new OutputStreamWriter(entityStream,"UTF-8"); t.store(writer, null); } }
ポイントは@Provider。これがあるとこいつはJAX-RSでの設定用ファイルだとみなされて、自動で登録される。
isWriteableメソッドがこのMessageBodyWriterの対象になるかどうかのboolean。writeToがストリームで出力する。
Entityの入力のときにももちろん利用可能。その場合はMessageBodyReaderを利用する。
あらゆるクラスを簡単に拡張できるのがわかっただろうか。Imageを戻り値に記述して"image/png"で出力する等も簡単にできるということ。引数を見るとわかるが、mimeも柔軟に対応できる。
おそらくJAX-RSを設計するに当たり、最も活躍するのがこのMessageBodyWriter/Reader。事実上のフィルタとして動作するため、開発者は単純にDTO用のBean等にアノテーションを目印としてつけてるだけで、自動で変換やヘッダ挿入も可能だ。
以下のようにwriteToに記述するとレスポンスヘッダに追加される。
httpHeaders.add("responseid", "hogehoge0001");
ヘッダを利用してコントロールするということはよくあると思うので覚えておきたい。