mike-neckのブログ

JavaかJavaFXかJavaEE(なんかJava8が多め)

Pixela の Java クライアントを書いてみた

f:id:mike_neck:20190120230012p:plain
くさ

先月に合同勉強会 in 大都会岡山に行った時に、草を生やす Pixela というサービスが面白そうだったので、 Java のクライアントがないか探してみたところ、なさそうだったので作ってみました。

github.com

ただ、かなり残念なことに、このクライアントは僕が Java11 の標準クライアントと Reactor の勉強がてら作ったというところもあり、

  • 最も多いであろう Java8 ユーザーは利用できません
  • 最も需要の高そうな同期呼び出しでは利用できません(ブロックできると言っちゃえば、まあ、それはそのとおりですが…)

あと、リリースどうしようか悩んでいるため、 maven からも入手できません。

ついでに言えば、まだ Webhook とか実装していません。


簡単な使い方の紹介

多分、 IDE で補完していけば大体のことはできるようになっています。若干 Reactor が邪魔くさいですが…

// クライアントを取得
final PixelaClient pixelaClient =  Pixela.withDefaultJavaClient();

// ユーザーをつくる
final Mono<Pixela> pixela = pixelaClient.createUser()
    .withToken("USER-TOKEN")
    .username("username")
    .agreeTermsOfService()
    .notMinor()
    .call();

// グラフをつくる
final Mono<Graph> graph = pixela.map(Pixela::createGraph)
    .map(cg -> cg.id("graph-id")
        .name("graph-name")
        .unit("commit")
        .shibafu()
        .timezone(ZoneId.of("Asia/Tokyo")))
    .flatMap(CreateGraph::call);

// 既存のグラフを increment する
final Mono<Graph> increment = pixela.map(p -> p.graph(GraphId.of("graph-id")))
    .map(Graph::incrementPixel)
    .flatMap(IncrementPixel::call);

HttpClient

そもそも、 Java8 で利用できないのは、 内部で使う pixela.client.http.HttpClient の実装に Java11 の標準のクライアント(java.net.http.HttpClient)を使っているからで、そうでない HttpClient を実装すれば Java8 でも使えます。ただ、 HttpClient という名前の割には、かなり多機能になっているインターフェースとなっています

public interface HttpClient extends AutoCloseable {

  @NotNull
  Mono<String> encodeJson(@NotNull Object object);

  @NotNull
  <T> Mono<T> decodeJson(@NotNull String json, @NotNull final Class<T> type);

  @NotNull
  <T> Mono<T> runAsync(@NotNull final Supplier<? extends T> supplier);

  @NotNull
  URI baseUri();

  @NotNull
  <T> Response<T> get(@NotNull final Get<T> getRequest);

  @NotNull
  <T> Response<T> post(@NotNull final Post<T> postRequest);

  @NotNull
  <T> Response<T> put(@NotNull final Put<T> putRequest);

  @NotNull
  <T> Response<T> delete(@NotNull final Delete<T> deleteRequest);
}

このインターフェースを実装して、 PixelaClientConfig から HttpClientインスタンスを返す HttpClientFactory を作って、それを META-INF/services/pixela.http.HttpClientFactory ファイルに指定すれば、先程記述した例の最初の部分 Pixela.withDefaultJavaClient() で作った HttpClient を利用できます。

インターフェースと実装を切り離せるようにしておきたいところもあるので、それをやったら、pixela-java-client-api/pixela-java-client-java-default という artifact で maven に載せようと思っています。


その他

ちなみに、このクライアント自体は昨年の年末年始の9連休に思い立って作り始めましたが、連休中のほとんどの時間はドラクエビルダーズ2に費やされ、ドラクエビルダーズ2の仕様的にイケてないところに何度もスクエニに問い合わせなどが発生する合間でこちらの作業をしていました。作るのに時間がかかったのはほぼそれが原因だと思っています。また、 Reactor をちゃんと理解していないあたりにも原因があるので、こちらは本気でちゃんとやらないといけないと思いました。