JAX-RSはセッションを自動で開始しない

どうやらJAX-RSで普通にアクセスするとセッションを新規に開始しないようだ。もちろん、すでに開始中の場合はセッションの保持時間を延長してくれる。ブラウザからのアクセスの場合まずどこかでhtmlを表示しているのでその後AJAX等でアクセスしてもセッションが引き継がれるので問題にはなりにくいのだが、Swing等単体のアプリだとそうはいかない。

もちろん、JAX-RSで意識的にセッションを発行することは出来る。通常業務アプリはまず最初にログイン画面があるため、ログイン認証のリソースでセッションクッキーを取得させればよい。クッキーを取得していないか、取得していてもログインしていなければはねさせる。これは通常のアプリと同じくフィルタではねると楽だろう。

セッションのIDはどこで取得すればいいかというとHttpServletRequest をインジェクトするのが一番楽。JAX-RSは@Contextアノテーションをつけることによってさまざまなものをインジェクトすることが出来る。

    @POST
    @ConsumeMime({MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML})
    @ProduceMime(MediaType.TEXT_PLAIN)
    public Response loginCheck(LoginForm form,@Context HttpServletRequest request){

        
        //本当はフォームを元にログイン判定処理を入れる
        String result = "Login OK";


        String id = request.getSession().getId();
        return Response.ok(result, MediaType.TEXT_PLAIN).
                cookie(new NewCookie("JSESSIONID", id) ).
                build();
    }

クライアントのほうは受け取ったクッキーを常に設定して接続すればよい。とりあえず受け取ったいろんな情報を出しまくってみる。

...
        
        Client c = Client.create();
        
        //接続するアドレス
        WebResource resource = c.resource(
                "http://localhost:8080/WebApplication5/resources/login"
                );

        //Responseのテスト
        {
            String jsonText = "{\"id\":\"shin\" , \"password\":\"hoge\"}";

            ClientResponse response = resource.type(MediaType.APPLICATION_JSON_TYPE).
                    cookie(new NewCookie("JSESSIONID", "hogehogehogehogehogehogehoge")).//2回目以降は受け取ったセッションクッキー
                    post(ClientResponse.class, jsonText);

            System.out.println("----------------------------");
            System.out.println("★パラメータ");
            System.out.println(jsonText);
            System.out.println("★結果");
            System.out.println("entityはあるかい?"+response.hasEntity());
            System.out.println(response.getEntity(String.class));
            System.out.println("tag:"+response.getEntityTag());
            System.out.println("クッキー一覧");
            for(Cookie cookie : response.getCookies()){
                System.out.println(cookie.getPath()+":"+cookie.getName() + "=" + cookie.getValue());
            }
            System.out.println("metadata一覧");
            for(Map.Entry<String,List<String>> entry: response.getMetadata().entrySet()){
                System.out.println(entry.getKey() +"="+entry.getValue().get(0));
            }
            System.out.println("プロパティ一覧");
            for(Map.Entry<String,Object> entry: response.getProperties().entrySet()){
                System.out.println(entry.getKey() +"="+entry.getValue());
            }
            System.out.printf("最終変更:%tF%n" ,response.getLastModified());
            System.out.println("status:"+response.getStatus());
            System.out.println("Language:"+response.getLanguage());
            System.out.println("type:"+response.getType().getType()+"/"+response.getType().getSubtype());
        }

クライアントだけではなく、サーバー側もかなり細かく設定することも可能だ。もちろんURLパラメータとクエリーパラメータの数字を足してその数字をステータスコードとして返すとかめちゃくちゃなことも可能。

面白いのがResponseを戻り値に設定するくせにResponseのstaticメソッドからスタートして最終的にbuild()するという点。戻り値に必要な型からスタートするのでIDE補完に頼ることが来て覚えやすく、非常に便利だ。