Google Cloud Endpoints(Java)のApiTransformer

2015-07-01T20:30:40+09:00 Java Google App Engine

公式ドキュメント: https://cloud.google.com/appengine/docs/java/endpoints/annotations#apitransformer

前回で省略した@ApiTransformerをやってみた

その前に余談

っていう事なので(ry

SampleApi.java

package sample;

import java.util.Arrays;
import java.util.List;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;

@Api(name = "sample")
public class SampleApi {
    @ApiMethod(path = "say")
    public List<Sample> getSay(Sample sample) {
        return Arrays.asList(sample);
    }
}

SampleApiTest.java

package sample;

import java.net.URL;
import java.util.List;
import java.util.Map;

import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.appengine.api.urlfetch.HTTPResponse;

import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalURLFetchServiceTestConfig;

import com.google.appengine.repackaged.com.google.gson.Gson;
import com.google.appengine.repackaged.com.google.gson.reflect.TypeToken;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

public class SampleApiTest {

    private final LocalServiceTestHelper testHelper = 
        new LocalServiceTestHelper(new LocalURLFetchServiceTestConfig());

    @Before
    public void setUp() {
        testHelper.setUp();
    }

    @After
    public void tearDown() {
        testHelper.tearDown();
    }

    @Test
    public void test() throws Exception {
        URLFetchService fetchService = URLFetchServiceFactory.getURLFetchService();
        URL url = new URL("http://localhost:8080/_ah/api/sample/v1/say?name=hoge");

        HTTPResponse response = fetchService.fetch(url);
        assertThat(response.getResponseCode(), is(200));

        Map<String, Object> parsedJson = new Gson().fromJson(
            new String(response.getContent()),
            // java.lang.reflect.Type
            new TypeToken<Map<String, Object>>() {}.getType()
        );
        assertThat(parsedJson, hasKey("items"));

        List<Object> items = (List<Object>)parsedJson.get("items");
        assertThat(items, hasSize(1));

        Map<String, String> item = (Map<String, String>)items.get(0);
        assertThat(item, hasKey("name"));
        assertThat(item.get("name"), is("hoge"));
    }
}

まぁ普通に/_ah/api/sample/v1/say?name=hogeなリクエストぶん投げてレスポンスをテストしているだけなのだけど、特に@ApiTransformerを介していないのでこのテストは無難に成功する

SampleApiTransformer.java

package sample;

import java.util.Map;
import java.util.HashMap;

import com.google.api.server.spi.config.Transformer;

public class SampleTransformer implements Transformer<Sample, Map<String, String>> {

    public Sample transformFrom(Map<String, String> in) {
        Sample sample = new Sample();
        sample.setName(in.get("name"));

        return sample;
    }

    public Map<String, String> transformTo(Sample in) {
        Map<String, String> out = new HashMap<String, String>(1);
        out.put("name", in.getName().toUpperCase());

        return out;
    }
}

な感じで特定の型に対して入力から型のインスタンスに変換(transformFrom)したり、特定の型をレスポンス出す際にデータを書式化してレスポンスだす(transformTo)等を実装する事が出来るっぽい。ちなみに@ApiResourceProperty(ignored)とかしててもこのレスポンスに変換する場合には関係無く出力されるのではないかと

でこれを使うには

package sample;

import java.io.Serializable;

import com.google.api.server.spi.config.AnnotationBoolean;
import com.google.api.server.spi.config.ApiResourceProperty;
import com.google.api.server.spi.config.ApiTransformer;

@ApiTransformer(SampleTransformer.class)
public class Sample implements Serializable {

    private int id;
    private String name;

    @ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

みたいに@ApiTransformerでつけてやれば良いっぽい。ちなみにAPIレベルでも付けれるらしいので、特定のAPIだけで有効したりなども出来るらしい(検証してない)

っていう事でこれを適応してから再度テストを実行するとSampleApiTransformerでtoUpperCaseしているのでテストはfailするようになる

HttpsURLConnection TrustManagerでPublic Key Pinning sedで改行を含めて削除する