Google Cloud Endpoints(Java)のApiTransformer
公式ドキュメント: https://cloud.google.com/appengine/docs/java/endpoints/annotations#apitransformer
前回で省略した@ApiTransformerをやってみた
その前に余談
gradle-appengine-pluginではsrc/functionalTestを用意する事でappengineFunctionalTestでテストを実行する前にサーバーをdaemon=trueで起動してテストを実行させる事が出来る模様
— kinjouj (@kinjou__j) 2015, 6月 30
っていう事なので(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するようになる