Support > Wagby Developer Network(R7) > REST API usage guide > [Application example] Using REST API in CAS environment
ja | en

I will explain how to use REST API in CAS environment. It is possible to call REST API using authentication with Windows Active Directory. R7.11.1

When calling REST API using CAS, first do "Log in to CAS (Acquire Ticket Granting Ticket)". TGT is used when acquiring ST (Service Ticket) described later.

After acquiring the TGT, each time you access the Wagby application, you get the ST (Service Ticket) corresponding to the URL to access. When accessing the Wagby application you also need to send ST together.

Here we introduce the sample code using the latest HttpClient 4.5 as of April 2017.

Log on to CAS

We will send the next request.

POST /cas/v1/tickets HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=admin&password=admin

Logging on to the Wagby application

First, get the Service Ticket for logon screen from CAS.

POST /cas/v1/tickets/{TGT} HTTP/1.1
Content-Type: application/x-www-form-urlencoded
service=http%3A%2F%2Flocalhost%3A8921%2Fwagby%2Frest%2Fsession

Log on to the Wagby application using Service Ticket (ST).

PUT /wagby/rest/session?ticket={ST} HTTP/1.1
Content-Type: application/x-www-form-urlencoded

Data acquisition

First, obtain a Service Ticket for customer details screen from CAS

POST /cas/v1/tickets/{TGT} HTTP/1.1
Content-Type: application/x-www-form-urlencoded
service=http%3A%2F%2Flocalhost%3A8921%2Fwagby%2Frest%2Fcustomer%2Fentry%2F1000

We will retrieve customer data using Service Ticket (ST).

GET /wagby/rest/customer/entry/1000?ticket={ST} HTTP/1.1

log off

First of all, we obtain Service Ticket for logoff from CAS.

POST /cas/v1/tickets/{TGT} HTTP/1.1
Content-Type: application/x-www-form-urlencoded
service=http%3A%2F%2Flocalhost%3A8921%2Fwagby%2Frest%2Fsession

Log off process using Service Ticket (ST).

DELETE /wagby/rest/session?ticket={ST} HTTP/1.1

After that, we will also log off the CAS.

DELETE /cas/v1/tickets/{TGT} HTTP/1.1

Sample code

The code is as follows.

/*
 * Copyright (C) Since 2006 JasmineSoft Inc. All Rights Reserved.
 */

package jp.jasminesoft.wagby.sample;

import java.io.IOException;
import java.net.URI;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

/**
 * HttpClient を使って REST API へアクセスを行うサンプルコードです。
 *
 * @author JasmineSoft
 * @version $Revision$ $Date$
 */
public class HttpClientSampleCAS {

    /**
     * メインメソッド
     * @param args コマンドライン引数
     */
    public static void main(String[] args) {

        // CAUTION: 以下のコードはエラーハンドリングを行っていません。
        //          各処理で発生した Exception を適切に処理するようにして下さい。
        BasicCookieStore cookieStore = new BasicCookieStore();
        String baseUrl = "http://localhost:8921/wagby/rest";

        // TGT(Ticket Granting Ticket) を取得します(CAS へログインする)。
        HttpUriRequest request = RequestBuilder.post()
                .setUri("http://localhost:18921/cas/v1/tickets")
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("username", "admin")
                .addParameter("password", "admin")
                .build();
        String content = execute(request);
        String tgtUrl = getTgtURL(content);

        // Wagby アプリケーションのログオン。
        // ログオン画面用の Service Ticket を CAS から取得します。
        String serviceUrl = baseUrl + "/session";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        String serviceTicket = execute(request);
        // ログオン。
        request = RequestBuilder.put()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .setHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        content = execute(request, cookieStore);

        // 顧客データを取得(主キー:1000)
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/entry/1000";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ取得処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // Wagby アプリケーションのログオフ。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/session";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // Wagby アプリケーションログオフ処理の実行。
        request = RequestBuilder.delete()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // CAS のログアウト。
        request = RequestBuilder.delete()
                .setUri(tgtUrl)
                .build();
        content = execute(request);
    }

    /**
     * 取得した HTML から TGT URL (form/@action 属性値)を取得します。
     * @param html HTML
     * @return TGT URL
     */
    private static String getTgtURL(String html) {
        Matcher matcher = Pattern.compile(
                ".*form action=\"([^\"]+)\".*").matcher(html);
        if (!matcher.matches()) {
            throw new IllegalStateException(
                    "Successful request, but no ticket found!");
        }
        return matcher.group(1);
    }

    /**
     * Executes HTTP request.
     * @param request the request to execute
     * @return String containing the content.
     */
    private static String execute(HttpUriRequest request) {
        return execute(request, null);
    }

    /**
     * Executes HTTP request.
     * @param request the request to execute
     * @param cookieStore CookieStore
     * @return String containing the content.
     */
    private static String execute(HttpUriRequest request,
            CookieStore cookieStore) {
        System.out.println("Executing request " + request.getRequestLine());

        try (CloseableHttpClient client = createDefaultClient(cookieStore);
                CloseableHttpResponse response = client.execute(request)) {

            //// Set-Cookie ヘッダをコンソールへ出力する。
            //for (Header header : response.getHeaders("Set-Cookie")) {
            //    System.out.println(
            //            header.getName() + " : " + header.getValue());
            //}
            int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
                // HTTP ステータスコードが 200 番台の場合のみ処理を行う。
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String content = EntityUtils.toString(entity);
                    System.out.println(content);
                    return content;
                }
                throw new IllegalStateException(
                        "Successful request, but response is empty!");
            } else {
                throw new ClientProtocolException(
                        "Unexpected response status: " + status);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * create Http client.
     * @param cookieStore CookieStore
     * @return Http client
     */
    private static CloseableHttpClient createDefaultClient(
            CookieStore cookieStore) {
        return HttpClients.custom()
                .setDefaultCookieStore(cookieStore)
                .setRedirectStrategy(new CustomRedirectStrategy()) // リダイレクト時の動作変更
                .build();
    }

    /**
     * リダイレクト時の動作を実装します。
     * - PUT リクエストもリダイレクト対象とします。
     * - 302 Found ( Moved Temporarily ) の PUT/POST/DELETE リクエスト時に
     *   リクエストメソッドを GET メソッドに変更せず、そのままのメソッド
     *   を維持したままリダイレクト処理を行います。
     *
     * @author JasmineSoft
     */
    public static class CustomRedirectStrategy extends LaxRedirectStrategy {

        /**
         * Redirectable methods.
         */
        private static final String[] REDIRECT_METHODS = new String[] {
            HttpPut.METHOD_NAME
        };

        /** {@inheritDoc} */
        @Override
        protected boolean isRedirectable(final String method) {
            boolean isRedirectable = super.isRedirectable(method);
            if (isRedirectable) {
                return true;
            }
            for (final String m: REDIRECT_METHODS) {
                if (m.equalsIgnoreCase(method)) {
                    return true;
                }
            }
            return false;
        }

        /** {@inheritDoc} */
        @Override
        public HttpUriRequest getRedirect(
                final HttpRequest request,
                final HttpResponse response,
                final HttpContext context) throws ProtocolException {
            final String method = request.getRequestLine().getMethod();
            if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)
                    || method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
                return super.getRedirect(request, response, context);
            }
            final URI uri = getLocationURI(request, response, context);
            return RequestBuilder.copy(request).setUri(uri).build();
        }
    }
}

About Redirect

Standard HttpClient behavior does not redirect PUT/POST/DELETE method requests at Http Status: 302 Found (Moved Temporarily).Therefore, in the sample above, we created the CustomRedirectStrategy class, and in these cases we also do the redirecting process.

Also, we change the standard behavior that "the request method will be changed to GET when redirecting the request of PUT/POST/DELETE method" and redirect processing is carried out while maintaining that method.

Also, when accessing the REST API via CAS in environments other than HttpClient, handle these redirect actions carefully.
With the curl command and Postman (Chrome application), we could redirect as intended without having to make special settings.(Confirmed as of April 2017)

Here is an example of list acquisition, registration, update and deletion based on the above sample code.Each procedure calls "Wagby's REST API using HttpClient> Register, update, deleteIt is the same as ".

/*
 * Copyright (C) Since 2006 JasmineSoft Inc. All Rights Reserved.
 */

package jp.jasminesoft.wagby.sample;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import jp.jasminesoft.jfc.app.JAXBJacksonModule;
import jp.jasminesoft.wagby.model.customer_p.CustomerP;
import jp.jasminesoft.wagby.model.customer_p.Deptname;
import jp.jasminesoft.wagby.model.customer_p.Kananame;
import jp.jasminesoft.wagby.model.customer_p.Name;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

/**
 * HttpClient を使って REST API へアクセスを行うサンプルコードです。
 *
 * @author JasmineSoft
 */
public class HttpClientSampleCAS {

    /**
     * メインメソッド
     * @param args コマンドライン引数
     */
    public static void main(String[] args) {

        // CAUTION: 以下のコードはエラーハンドリングを行っていません。
        //          各処理で発生した Exception を適切に処理するようにして下さい。
        BasicCookieStore cookieStore = new BasicCookieStore();
        String baseUrl = "http://localhost:8921/wagby/rest";

        // TGT(Ticket Granting Ticket) を取得します(CAS へログインする)。
        HttpUriRequest request = RequestBuilder.post()
                .setUri("http://localhost:18921/cas/v1/tickets")
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("username", "admin")
                .addParameter("password", "admin")
                .build();
        String content = execute(request);
        String tgtUrl = getTgtURL(content);

        // Wagby アプリケーションのログオン。
        // ログオン画面用の Service Ticket を CAS から取得します。
        String serviceUrl = baseUrl + "/session";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        String serviceTicket = execute(request);
        // ログオン。
        request = RequestBuilder.put()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .setHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        content = execute(request, cookieStore);

        // ログオン状態の確認。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/session";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // ログオン状態の確認処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 顧客一覧を取得(検索条件なし)
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/list";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客一覧取得処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 顧客一覧を取得(顧客名「ジャスミン太郎」で検索)。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/list";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客一覧取得処理の実行。
        request = RequestBuilder.post()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("customer_cp$002fname", "ジャスミン太郎")
                .build();
        content = execute(request, cookieStore);

        // json:顧客一覧を取得(顧客名「ジャスミン太郎」で検索)。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/list";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // json:顧客一覧取得処理の実行。
        String json = "{ \"name\": {\"content\":\"ジャスミン太郎\"}}";
        request = RequestBuilder.post()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .setHeader("Content-Type", "application/json")
                .setEntity(new StringEntity(json, Consts.UTF_8))
                .build();
        content = execute(request, cookieStore);

        // 顧客データを取得(主キー:1000)
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/entry/1000";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ取得処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 顧客データの新規登録開始(初期値が埋まった状態のデータが取得できる)。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/new";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ新規登録開始処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 取得した json データの entityp フィールドを CustomerP に変換
        CustomerP customer_p = toObject(
                toJsonNode(content).get("entityp"), CustomerP.class);
        // name 項目に「ジャスミン三郎」を指定
        Name name = new Name();
        name.setContent("ジャスミン三郎");
        customer_p.setName(name);
        //customer_p.setName(new Name());
        //customer_p.getName().setContent("ジャスミン三郎");
        // kananame 項目に「ジャスミンサブロウ」を指定
        Kananame kananame = new Kananame();
        kananame.setContent("ジャスミンサブロウ");
        customer_p.setKananame(kananame);
        //customer_p.setKananame(new Kananame());
        //customer_p.getKananame().setContent("ジャスミンサブロウ");

        // 顧客データの新規登録(保存)。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/new";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ保存処理の実行。
        request = RequestBuilder.post()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .setHeader("Content-Type", "application/json")
                .setEntity(new StringEntity(toJson(customer_p), Consts.UTF_8))
                .build();
        content = execute(request, cookieStore);

        // 登録時に自動採番された主キーを取得。
        // 取得した json データの pkey フィールドが主キー値となっている。
        String pkey = toJsonNode(content).get("pkey").textValue();

        // 顧客データの更新開始。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/edit/" + pkey;
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ更新開始処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 取得した json データの entityp フィールドを CustomerP に変換
        customer_p = toObject(
                toJsonNode(content).get("entityp"), CustomerP.class);
        // deptname 項目に「営業部」を指定
        Deptname deptname = new Deptname();
        deptname.setContent("営業部");
        customer_p.setDeptname(deptname);
        //customer_p.setDeptname(new Deptname());
        //customer_p.getDeptname().setContent("営業部");

        // 顧客データの更新(保存)。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/edit/" + pkey;
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 顧客データ保存処理の実行。
        request = RequestBuilder.put()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .setHeader("Content-Type", "application/json")
                .setEntity(new StringEntity(toJson(customer_p), Consts.UTF_8))
                .build();
        content = execute(request, cookieStore);

        // 顧客データを取得(正しく更新されているか確認)
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/entry/" + pkey;
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 処理の実行。
        request = RequestBuilder.get()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // 顧客データを削除(主キー:1000)
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/customer/edit/" + pkey;
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // 処理の実行。
        request = RequestBuilder.delete()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // Wagby アプリケーションのログオフ。
        // Service Ticket を CAS から取得します。
        serviceUrl = baseUrl + "/session";
        request = RequestBuilder.post()
                .setUri(tgtUrl)
                //.setHeader("Content-Type", "application/x-www-form-urlencoded") // HttpClient では省略可
                .addParameter("service", serviceUrl)
                .build();
        serviceTicket = execute(request);
        // Wagby アプリケーションログオフ処理の実行。
        request = RequestBuilder.delete()
                .setUri(serviceUrl + "?ticket=" + serviceTicket)
                .build();
        content = execute(request, cookieStore);

        // CAS のログアウト。
        request = RequestBuilder.delete()
                .setUri(tgtUrl)
                .build();
        content = execute(request);
    }

    /**
     * 取得した HTML から TGT URL (form/@action 属性値)を取得します。
     * @param html HTML
     * @return TGT URL
     */
    private static String getTgtURL(String html) {
        Matcher matcher = Pattern.compile(
                ".*form action=\"([^\"]+)\".*").matcher(html);
        if (!matcher.matches()) {
            throw new IllegalStateException(
                    "Successful request, but no ticket found!");
        }
        return matcher.group(1);
    }

    /**
     * Executes HTTP request.
     * @param request the request to execute
     * @return String containing the content.
     */
    private static String execute(HttpUriRequest request) {
        return execute(request, null);
    }

    /**
     * Executes HTTP request.
     * @param request the request to execute
     * @param cookieStore CookieStore
     * @return String containing the content.
     */
    private static String execute(HttpUriRequest request,
            CookieStore cookieStore) {
        System.out.println("Executing request " + request.getRequestLine());

        try (CloseableHttpClient client = createDefaultClient(cookieStore);
                CloseableHttpResponse response = client.execute(request)) {

            //// Set-Cookie ヘッダをコンソールへ出力する。
            //for (Header header : response.getHeaders("Set-Cookie")) {
            //    System.out.println(
            //            header.getName() + " : " + header.getValue());
            //}
            int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
                // HTTP ステータスコードが 200 番台の場合のみ処理を行う。
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String content = EntityUtils.toString(entity);
                    System.out.println(content);
                    return content;
                }
                throw new IllegalStateException(
                        "Successful request, but response is empty!");
            } else {
                throw new ClientProtocolException(
                        "Unexpected response status: " + status);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * create Http client.
     * @param cookieStore CookieStore
     * @return Http client
     */
    private static CloseableHttpClient createDefaultClient(
            CookieStore cookieStore) {
        return HttpClients.custom()
                .setDefaultCookieStore(cookieStore)
                .setRedirectStrategy(new CustomRedirectStrategy()) // リダイレクト時の動作変更
                .build();
    }

    /**
     * Java オブジェクトを JSON 文字列に変換します。
     * @param value 変換対象の Java オブジェクト
     * @return Java オブジェクトを変換した JSON 文字列
     */
    private static String toJson(Object value) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * JSON 文字列を JsonNode に変換します。
     * @param json JSON 文字列
     * @return JsonNode
     */
    private static JsonNode toJsonNode(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readTree(json);
        } catch (JsonParseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * JsonNode を clazz のインスタンスに変換します。
     * @param <P> 変換後のクラスの型
     * @param node JsonNode
     * @param clazz 変換後のクラス
     * @return clazz のインスタンス
     */
    private static <P> P toObject(JsonNode node, Class<P> clazz) {
        return toObject(node.toString(), clazz);
    }

    /**
     * JSON 文字列を clazz のインスタンスに変換します。
     * @param <P> 変換後のクラスの型
     * @param json JSON 文字列
     * @param clazz 変換後のクラス
     * @return clazz のインスタンス
     */
    private static <P> P toObject(String json, Class<P> clazz) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JAXBJacksonModule()); // JAXB のアノテーションを利用した変換ルール
        try {
            return mapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * リダイレクト時の動作を実装します。
     * - PUT リクエストもリダイレクト対象とします。
     * - 302 Found ( Moved Temporarily ) の PUT/POST/DELETE リクエスト時に
     *   リクエストメソッドを GET メソッドに変更せず、そのままのメソッド
     *   を維持したままリダイレクト処理を行います。
     *
     * @author JasmineSoft
     * @version $Revision$ $Date$
     */
    public static class CustomRedirectStrategy extends LaxRedirectStrategy {

        /**
         * Redirectable methods.
         */
        private static final String[] REDIRECT_METHODS = new String[] {
            HttpPut.METHOD_NAME
        };

        /** {@inheritDoc} */
        @Override
        protected boolean isRedirectable(final String method) {
            boolean isRedirectable = super.isRedirectable(method);
            if (isRedirectable) {
                return true;
            }
            for (final String m: REDIRECT_METHODS) {
                if (m.equalsIgnoreCase(method)) {
                    return true;
                }
            }
            return false;
        }

        /** {@inheritDoc} */
        @Override
        public HttpUriRequest getRedirect(
                final HttpRequest request,
                final HttpResponse response,
                final HttpContext context) throws ProtocolException {
            final String method = request.getRequestLine().getMethod();
            if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)
                    || method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
                return super.getRedirect(request, response, context);
            }
            final URI uri = getLocationURI(request, response, context);
            return RequestBuilder.copy(request).setUri(uri).build();
        }
    }
}