JAX-RSでJSONやXMLをPOSTしてみる

前回(JAX-RSでJSONやXMLを返す)JSONXMLを取得するところまで行った。

今回はJSONXMLをポストしてみる。サーバー側はBeansとして受け取れるだろうか。

サーバー側プログラム

前回のコードを一部変更する。具体的には以下のメソッドを追加した。

その他のコードは前回の記事を参考に。DTOはJAXB対応であることの証明である@XmlRootElementアノテーションをクラスの先頭に1行つけるだけなので楽チンだ。

@POST
@ConsumeMime({MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML})
@ProduceMime(MediaType.TEXT_PLAIN)
public String postCustomer(Customer c){
    String result = String.format(
            "なまえは%s\nじゅうしょは%s\n",
            c.名前 , 
            c.住所
            );
    return result;
}

今回は文字列でMIMEをセットしたのではなく、定数クラスから取得するようにした。

@ConsumeMimeが送信側のMIMEで@ProduceMimeが結果のMIMEでいいらしい。

クライアントプログラム

前回は標準APIでアクセスしたが、はっきり言って記述するコードが多すぎるので今回は楽をするためにjersey(JAX-RSのリファレンス実装)を使う。

package jaxrs;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import javax.ws.rs.core.MediaType;

public class PostTest {

    public static void main(String[] args) {
        
        Client c = Client.create();
        //接続するアドレス
        WebResource resource = c.resource(
                "http://localhost:8080/WebApplication5/resources/customers"
                );

        //JSONでPOST
        {
            String jsonText = "{\"得意先\":{\"名前\":\"shin\",\"住所\":\"shinの住所\"}} ";
            String response = resource.type(MediaType.APPLICATION_JSON_TYPE).
                    post(String.class, jsonText);
            System.out.println("----------------------------");
            System.out.println("★パラメータ");
            System.out.println(jsonText);
            System.out.println("★結果");
            System.out.println(response);
        }

        //XMLでPOST
        {
            String xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
                    "<得意先>\n"+
                    "    <名前>shin</名前>\n"+
                    "    <住所>shinの住所</住所>\n"+
                    "</得意先>";
            String response = resource.type(MediaType.APPLICATION_XML_TYPE).
                    post(String.class, xmlText);
            System.out.println("----------------------------");
            System.out.println("★パラメータ");
            System.out.println(xmlText);
            System.out.println("★結果");
            System.out.println(response);
        }
        
        
    }

}

結果

----------------------------
★パラメータ
{"得意先":{"名前":"shin","住所":"shinの住所"}} 
★結果
なまえはshin
じゅうしょはshinの住所

----------------------------
★パラメータ
<?xml version="1.0" encoding="UTF-8"?>
<得意先>
    <名前>shin</名前>
    <住所>shinの住所</住所>
</得意先>
★結果
なまえはshin
じゅうしょはshinの住所

非常にシンプル。JSONXMLとの変換はパラメータ受け取りにおいても全自動のようだ。


わざと構文のおかしいXMLJSONを渡すともちろんエラー。ただし、JAX-RSのコード側にはエラーは来ない。URLのミスにおいてもエラーは来ないし、サーブレットの段階でとまってくれているのでかなり開発する側はらくだと思う。

もしも、エラーも含めて処理をしたいとかカスタマイズした変換がほしいのならMessageBodyReaderとかを使うのだろうが、通常の用途においては必要性は感じられない。文字コードUTF-8以外にしたいということも今では少ないと思うし。ちなみに今回も前回もわざと日本語のエレメントやフィールドを入れている。まったく問題ないことから日本語対応もばっちりだろう。


JAX-RSは数々のJavaEEAPIの中では珍しく「ちゃんとすぐに簡単に使える」というのがわかりやすいAPIだと思う。ただ、テストのためにRESTクライアントも標準APIにしてくれたほうが助かるんだけどなぁ。「com.sun」パッケージだとちょっと押しが弱い気がする。


ポイントは送信も受信もクライアント側が自由にJSONXMLを選択できること。使用する側が選択できる余地を残しておくことは重要だと思う。そしてXMLJSONとでロジックは一切かわらないし。あとはさらにJAX-WS対応してSOAPクライアントにも優しくなるというのもありかなと思ったけど、大概SOAPを使ったシステムの場合クライアントもサーバーと同じ場合が多く、WSDLから自動生成で互換性を求めることはJavaと.NET以外ではかなり非現実的なことを考えるとJAX-RSだけでいいのかもしれない。おそらくjerseyクライアントもちゃんとJAXBのクラスを渡すことだって出来るはずだ。